MrJShen commited on
Commit
598008a
·
1 Parent(s): 35a55b8

Upload 23 files

Browse files
app.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+
3
+ import sys
4
+ import time
5
+ from io import StringIO
6
+ import streamlit as st
7
+ from PIL import Image, ImageDraw, ImageColor
8
+ from canvas import *
9
+ from streamlit_ace import st_ace
10
+ import extra_streamlit_components as stx
11
+ from streamlit_image_select import image_select
12
+ from sewar.full_ref import uqi
13
+ import numpy as np
14
+ # from sqlite3 import Connection
15
+ import datetime
16
+ from lines import *
17
+ from triangle import *
18
+
19
+
20
+ def get_manager():
21
+ return stx.CookieManager()
22
+
23
+ #### Manage Cookies and ajs_state ####
24
+
25
+ #time.sleep(3)
26
+ #cookie_manager = get_manager()
27
+ #ajs_id = cookie_manager.get_all()["ajs_anonymous_id"]
28
+ date_reg = datetime.date.today().strftime("%d/%m/%Y")
29
+ st.session_state['timestamp'] = datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")
30
+
31
+ #st.session_state['conn'] = get_connection("data_drawer.db")
32
+ #user_checked = check_value_id_user(st.session_state.conn, ajs_id).values[0][0] > 0
33
+ #if not user_checked:
34
+ # user_id = str(st.text_input("Welcome! please enter your username here:)"))
35
+ # values = (ajs_id, user_id, date_reg)
36
+ # insert_value_ajs_states (st.session_state.conn, values)
37
+
38
+ ## Sidebar for color picker
39
+ with st.sidebar:
40
+ color = st.color_picker('color picker', '#00f900', key='l_c')
41
+ st.write(ImageColor.getrgb(color))
42
+
43
+ st.header("Shape Puzzles")
44
+ st.write("##")
45
+ st.divider()
46
+
47
+ st.markdown("###### Write your code here")
48
+ ## Code input
49
+ code = st_ace(
50
+ language="python",
51
+ theme="tomorrow_night_bright",
52
+ keybinding="vscode",
53
+ font_size=14,
54
+ tab_size=4,
55
+ show_gutter=True,
56
+ min_lines=10,
57
+ key="ace",
58
+ )
59
+ st.divider()
60
+
61
+ target = image_select(
62
+ label="Select a target image",
63
+ images=[
64
+ 'image/TrianglePolygon.png',
65
+ 'image/TriangleHole.png',
66
+ "image/TriangleCrash.png",
67
+ 'image/archillect.png',
68
+ 'image/TriangleFox.png'
69
+ ],
70
+ captions=["Iterative Polygon", "Infinite traps", "One Cut", "Archillect", "Red Fox"],
71
+ use_container_width = False
72
+ )
73
+
74
+ o1, o2 = st.columns(2)
75
+ if code:
76
+ ImageDraw.Draw(img).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
77
+ redirected_output = sys.stdout = StringIO()
78
+ try:
79
+ exec(code)
80
+ result = str(redirected_output.getvalue())
81
+ st.code(result)
82
+ except Exception as e:
83
+ st.code(str(e))
84
+
85
+ st.write("##")
86
+ st.divider()
87
+ with o1:
88
+ st.markdown("##### Target Shape:")
89
+ target = Image.open(target)
90
+ t2 = target.resize((c_length,c_height))
91
+ ImageDraw.Draw(img_t).rectangle([(0, 0),
92
+ (c_length,c_height)],
93
+ fill = c_color,
94
+ outline = c_outline,
95
+ width=2)
96
+ img_t.paste(t2)
97
+ st.image(img_t)
98
+ st.session_state['imt'] = np.array(img_t)
99
+ with o2:
100
+ st.markdown("##### Output Shape")
101
+ st.image(img, caption='')
102
+ st.session_state['imo'] = np.array(img)
103
+
104
+ #### Measuring Similarity
105
+ sim = round(uqi(st.session_state['imt'],st.session_state['imo']),4)
106
+
107
+ st.write(f"Similarity Score: {sim}")
108
+
canvas.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image, ImageDraw
2
+
3
+ ## Canvas Config
4
+ c_length = 700
5
+ c_height = 600
6
+ c_mode = 'RGB'
7
+ c_color = (250,250,250)
8
+ c_outline = (0,0,0)
9
+
10
+ img = Image.new(c_mode, (c_length, c_height), color = c_color)
11
+ img_t = Image.new(c_mode, (c_length, c_height), color = c_color)
12
+
13
+ draw = ImageDraw.Draw(img)
circle.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image, ImageDraw
2
+ import math
3
+ import numpy as np
4
+ from canvas import *
5
+
6
+
7
+ def _re_coord(point,x=c_length/2,y=c_height/2):
8
+ return (point[0]+x, y-point[1])
9
+
10
+ def _back_coord(point):
11
+ return (point[0]-c_length/2, c_height/2-point[1])
12
+
13
+ def circle_c_r(center, radiu, fill = None, color = (0,0,0), width = 1):
14
+ ce = _re_coord(center)
15
+ p1 = (ce[0]- radiu/math.sqrt(2), ce[1] - radiu/math.sqrt(2))
16
+ p2 = (ce[0]+ radiu/math.sqrt(2), ce[1] + radiu/math.sqrt(2))
17
+ draw.pieslice([p1,p2], start=0, end=360, fill=fill, outline=color, width=width)
18
+ data = {'center':center,
19
+ 'radiu':radiu,
20
+ 'arc':math.pi*2*radiu}
21
+ return data
22
+
23
+ def circle_draw(point, diameter, angle=0, fill = None, color = (0,0,0), width = 1):
24
+ po = _re_coord(point); radiu = diameter/2
25
+ x_e = radiu * math.cos(-angle); y_e = radiu*math.sin(-angle)
26
+ ce = (po[0]-x_e, po[1]-y_e)
27
+ p1 = (ce[0]- radiu/math.sqrt(2), ce[1] - radiu/math.sqrt(2))
28
+ p2 = (ce[0]+ radiu/math.sqrt(2), ce[1] + radiu/math.sqrt(2))
29
+ draw.pieslice([p1,p2], start=0, end=360, fill=fill, outline=color, width=width)
30
+ data = {'center':_back_coord(ce),
31
+ 'radiu':radiu,
32
+ 'arc':math.pi*2*radiu}
33
+ return data
34
+
image/T1.jpg ADDED
image/T1_t.jpg ADDED
image/T2_1.jpg ADDED
image/T2_t.jpg ADDED
image/T3_t.jpg ADDED
image/TriangleCrash.png ADDED
image/TriangleFox.png ADDED
image/TriangleHole.png ADDED
image/TrianglePolygon.png ADDED
image/archillect.png ADDED
image/archillect.pngZone.Identifier ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ [ZoneTransfer]
2
+ ZoneId=3
3
+ ReferrerUrl=https://i.ibb.co/1nB6XkF/archillect.png
4
+ HostUrl=https://i.ibb.co/1nB6XkF/archillect.png
img.png ADDED
img_t.png ADDED
lines.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image, ImageDraw
2
+ import numpy as np
3
+ import math
4
+ import shapely
5
+ from shapely.geometry import LineString
6
+ from canvas import *
7
+
8
+
9
+ def _re_coord(point):
10
+ return (point[0]+c_length/2, c_height/2-point[1])
11
+
12
+ def _back_coord(point):
13
+ return (point[0]-c_length/2, c_height/2-point[1])
14
+
15
+ def line_end(start, angle, length):
16
+ x, y = start
17
+ endy = y + length * math.sin(math.radians(-angle))
18
+ endx = x + length * math.cos(math.radians(-angle))
19
+ return (endx, endy)
20
+
21
+ def lines_intersection(l1, l2):
22
+ line1 = LineString([l1['start'], l1['end']])
23
+ line2 = LineString([l2['start'], l2['end']])
24
+ int_pt = line1.intersection(line2)
25
+ return (int_pt.x, int_pt.y)
26
+
27
+ def p2d (start, end):
28
+ angle = np.rad2deg(np.arctan2(end[1] - start[1], end[0] - start[0]))
29
+ dist = np.linalg.norm(np.array(start) - np.array(end))
30
+ x_range = (start[0], end[0])
31
+ mid_point = ((start[0]+end[0])/2, (start[1]+end[1])/2)
32
+ data = {
33
+ 'angle':angle,
34
+ 'dist':dist,
35
+ 'x_range':x_range,
36
+ 'mid_point':mid_point
37
+ }
38
+ return data
39
+
40
+ def line2P(start,end,color=(0,0,0),width=1):
41
+ draw.line([_re_coord(start), _re_coord(end)], fill=color, width=width, joint=None)
42
+ data = {'start':start,
43
+ 'end':end}
44
+ return data
45
+
46
+ def lineDraw(start, angle, length, color=(0,0,0), width=1):
47
+ end = line_end(_re_coord(start), angle, length)
48
+ draw.line([_re_coord(start), end], fill=color, width=width, joint=None)
49
+ data = {'start':start,
50
+ 'end':_back_coord(end)}
51
+ return data
52
+
53
+ def lineFunc(x_range, alpha=1, const = 0, color=(0,0,0), width=1):
54
+ start_x = x_range[0]-c_length/2
55
+ end_x =x_range[-1]-c_length/2 #the last one of range
56
+ start_y = c_height - (alpha*start_x + const)
57
+ end_y = c_height - (alpha*end_x + const)
58
+ draw.line([(start_x,start_y), (end_x, end_y)], fill=color, width=width, joint=None)
59
+ data = {'start':(start_x,start_y),
60
+ 'end':(end_x,end_y)}
61
+ return data
pages/1_Chapter_1 Lines and Triangles.py ADDED
@@ -0,0 +1,411 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from io import StringIO
3
+ import streamlit as st
4
+ import numpy as np
5
+ from PIL import Image, ImageDraw, ImageColor
6
+ from canvas import *
7
+ from streamlit_ace import st_ace
8
+ import extra_streamlit_components as stx
9
+ from sewar.full_ref import uqi
10
+ from lines import *
11
+ from triangle import *
12
+
13
+ st.set_page_config(page_title="How to play Shape Puzzle", page_icon=":notebook:")
14
+
15
+
16
+ with st.sidebar:
17
+ color = st.color_picker('color picker', '#00f900', key='l_c')
18
+ st.write(ImageColor.getrgb(color))
19
+
20
+ st.header("Chapter 1: Lines and Triangles")
21
+ st.write("##")
22
+ st.divider()
23
+
24
+ with st.expander("Tutorial No.1: Line segments"):
25
+
26
+ st.markdown("#### Let's start with playing with line-segments")
27
+ st.markdown(
28
+ """
29
+ 1. We will firstly draw a simple line-segment. The easiest way to do so is using our line function:
30
+ ```python
31
+ line2P(start, point)
32
+ ```
33
+ - In the code window below, define two points on the canvas by:
34
+
35
+ ```python
36
+ a = (-100, 0) ## the x-axis is -100 and y-axis is 0
37
+ b = (100, 0) ## the x-axis is 100 and y-axis is 0
38
+ line2P(a, b) ## then call our line2P function to draw the line
39
+ ```
40
+
41
+ You should see a horizontal line-segment in the canvas.
42
+ Feel free to change the color or the width of drawing by refering the "Functions" page from side bar.
43
+
44
+ 2. Our 2nd Line function, LineDraw():
45
+ Sometimes, it might be easier to just start from a single point, but thinking about the direction and the length of drawing a
46
+ line segment. This is more intuitive for the real drawing scenario.
47
+
48
+ - In the code window below, define a point and the length and angle you want to draw :
49
+
50
+ ```python
51
+ a = (-100, 0) ## the x-axis is -100 and y-axis is 0
52
+ angle = 45 ## 45 degree anti-clock wise
53
+ length = 200 ## length of the drawing
54
+ lineDraw(a, angle, length, width=50) ## then call our lineDraw function to draw the line
55
+ ## We can also specify the width of drawing by passing parameter explicitly.
56
+ ```
57
+
58
+ You should see a slant line-segment in the canvas.
59
+
60
+ 3. Release the power of for-loop:
61
+ The most powerful part of drawing through code is the capability of producing iterative graphs.
62
+ The more detailed instruction about Python for-loops, please check [here](https://www.w3schools.com/python/python_for_loops.asp)
63
+
64
+ - In the code window below, define a startinig point and using for-loop and lineDraw:
65
+
66
+ ```python
67
+ c = (-50,-100) ## The starting point to draw
68
+ lst = [c] ## Create a list for later reference
69
+ for i in range (100): ## Iterate 100 rounds
70
+ l = lineDraw(lst[-1], i*125, 300, (212, 16, 16), width=2) ## Try to figure out what are we doing here?
71
+ lst.append(l['end']) ## add the end-point of the line drawn to the list for the next iteration
72
+ ```
73
+ 4. Now, see if you can produce a shape stated in "target shape":
74
+
75
+ ```python
76
+ s = (0,0) ## The starting point
77
+ n = 8 ##
78
+ lst = [s]
79
+
80
+ #### Start your for-loop here ####
81
+
82
+ #### End of your for-loop ####
83
+ ```
84
+ Having fun!!
85
+ """
86
+ )
87
+
88
+ st.divider()
89
+ st.markdown("###### Write your code here")
90
+ ## Code input
91
+ code1 = st_ace(language="python", theme="tomorrow_night_bright", keybinding="vscode", font_size=14, tab_size=4, show_gutter=True, min_lines=10, key="ace",)
92
+ o1, o2 = st.columns(2)
93
+ if code1:
94
+ ImageDraw.Draw(img).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
95
+ redirected_output = sys.stdout = StringIO()
96
+ try:
97
+ exec(code1)
98
+ result = str(redirected_output.getvalue())
99
+ st.code(result)
100
+ except Exception as e:
101
+ st.code(str(e))
102
+ with o1:
103
+ st.markdown("##### Target Shape:"); target = Image.open('image/T1_t.jpg')
104
+ t2 = target.resize((c_length,c_height))
105
+ ImageDraw.Draw(img_t).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
106
+ img_t.paste(t2); st.image(img_t); st.session_state['imt'] = np.array(img_t)
107
+ with o2:
108
+ st.markdown("##### Output Shape"); st.image(img, caption=''); st.session_state['imo'] = np.array(img)
109
+
110
+ sim = round(uqi(st.session_state['imt'],st.session_state['imo']),4)
111
+ st.write(f"The similarity score between target and output: {sim}")
112
+
113
+
114
+ with st.expander("Tutorial No.2: Triangles and Transformations 1"):
115
+
116
+ st.markdown("Now, we will start to draw more cool shapes")
117
+ st.markdown(
118
+ """
119
+ 1. The simplest way to draw a triangle is to define three points on the canvas:
120
+
121
+ - In the code window below, define two points on the canvas by:
122
+
123
+ ```python
124
+ a = (-100, 0) ## the x-axis is -100 and y-axis is 0
125
+ b = (100, 0) ## the x-axis is 100 and y-axis is 0
126
+ c = (0, 200) ## the x-axis is 0 and y-axis is 200
127
+ triangle_base(a,b,c, fill = (0, 249, 0), color=(0,0,0)) ## then call our basic triangle function to draw the shape
128
+
129
+ ```
130
+
131
+ You should see a isosceles triangle in the canvas.
132
+ In the triangle_base() function, we have two parameters for coloring:
133
+ -- the "fill" is for the color filled in the triangle
134
+ -- the "color" is color of the edge of the triangle
135
+
136
+
137
+ 2. Our 2nd Triangle function, triangle_LP():
138
+
139
+ Again, it might be easier to just start from a line, but thinking about another point to draw a
140
+ triangle. This is convient for some scenario when iteration applies.
141
+
142
+ - In the code window below, try the follow drawing:
143
+
144
+ ```python
145
+ for i in range (10): # We create an iteration of 10
146
+
147
+ # Each iteration, draw a line with one different end point per iter
148
+ l = line2P((100,0+i*10),(-300,100), (0, 249, 0))
149
+ # then for each different line drawn, touch it to a fixed point (150,150) to form a triangle
150
+ triangle_LP(l, (150,150), (0, 249, 0))
151
+ ```
152
+
153
+ You should see a repeated triangle shape in the canvas.
154
+
155
+ 3. Transform of shapes 1: Rescale:
156
+
157
+ Shape transformations are very helpful functions in drawing shapes.
158
+
159
+ The first transformation we are trying is Rescale,
160
+
161
+ - In the code window below, define a startinig triangle from triangle_base() and then scale it:
162
+
163
+ ```python
164
+ a = (-100, 0) ## the x-axis is -100 and y-axis is 0
165
+ b = (100, 0) ## the x-axis is 100 and y-axis is 0
166
+ c = (0, 200) ## the x-axis is 0 and y-axis is 200
167
+ ### Our initial triangle, give it a name, t
168
+ t = triangle_base(a,b,c, fill = (0, 249, 0), color=(0, 249, 0))
169
+
170
+ ### we rescale it with half size
171
+ ### 1. We use the default color here, which was filled with canvas color and edge with black
172
+ ### 2. We choose redraw=False, this means keep the original triangle t
173
+ ##### 2.5 If we are passing redraw=True, the t will disappear.
174
+ t2 = rescale_c(t, alpha=0.5, redraw=False)
175
+ ```
176
+
177
+ You might already see a chance of creating a for-loop for some great design?
178
+
179
+ The rescale function we used above is rescaling based on centre of triangle, we can also use another
180
+ rescale function rescale_p() to specify the point we want to base on for rescaling.
181
+
182
+ - In the code window below, following the code from above, paste the next snippet
183
+
184
+ ```python
185
+ a = (-100, 0) ## the x-axis is -100 and y-axis is 0
186
+ b = (100, 0) ## the x-axis is 100 and y-axis is 0
187
+ c = (0, -200) ## the x-axis is 0 and y-axis is 200
188
+ ### Our initial triangle, give it a name, t
189
+ t3 = triangle_base(a,b,c, fill = (201, 64, 26), color=(201, 64, 26))
190
+
191
+ ### we rescale it with half size, but at different point
192
+ t4 = rescale_p(t3, 'p2', alpha=0.5, redraw=False)
193
+ ```
194
+
195
+ 4. Transform of shapes 2: Translation:
196
+
197
+ The second transformation we are introducing is translation,
198
+
199
+ - In the code window below, define a startinig triangle from triangle_base() and then Translate it
200
+ to different location:
201
+
202
+ ```python
203
+ a = (-200, 0) ## the x-axis is -100 and y-axis is 0
204
+ b = (10, 0) ## the x-axis is 100 and y-axis is 0
205
+ c = (0, -100) ## the x-axis is 0 and y-axis is 200
206
+ ### Our initial triangle, give it a name, t
207
+ t5 = triangle_base(a,b,c, fill = (201, 64, 26), color=(201, 64, 26))
208
+
209
+ ## We use vector here to specify the direction and magnitute of translation.
210
+ ## The translate_o() function is traslating triangles by a vector defined from the
211
+ ## origin. i.e. the center of the canvas.
212
+ t6 = translate_o(t3, vector = (100,150), redraw=False)
213
+ ```
214
+
215
+ Now we should try the effect of translate by a vector defined from a point of the triangle
216
+
217
+ - In the code window below, define a startinig triangle from triangle_base() and then Translate it
218
+ to different location, using translate_p() function:
219
+
220
+ ```python
221
+ a = (-20, 0) ## the x-axis is -100 and y-axis is 0
222
+ b = (10, 0) ## the x-axis is 100 and y-axis is 0
223
+ c = (0, -100) ## the x-axis is 0 and y-axis is 200
224
+ ### Our initial triangle, give it a name, t
225
+ t7 = triangle_base(a,b,c, fill = (201, 64, 26), color=(201, 64, 26))
226
+
227
+ translate_p(t7, vector = (-10,10), point = 'p2', redraw=False)
228
+ ```
229
+ The code above specify "P2" as origin of translation rather than center of canvas
230
+
231
+ 5. Using data for more complicated design:
232
+
233
+ Read the code below and check out the output from a more specific design
234
+
235
+ ```python
236
+ b_line = line2P((-200,-160),(200,-160),color='black') # set the baseline
237
+ tpoint = (0,200) # set the top point of the triangle
238
+
239
+ # Create the first triangle
240
+ t1 = triangle_LP(b_line,tpoint,color='black',fill='black')
241
+ # Translate the triangle_LP
242
+ down_vector = (0,-50)
243
+ t2 = translate_o(t1, down_vector,fill=None, redraw=False)
244
+
245
+ # Redraw the edge of the second triangle
246
+
247
+ l1 = line2P(t2['p1'], t2['p2'], color='white', width=10)
248
+ l2 = line2P(t2['p1'], t2['p3'], color='white', width=10)
249
+ l3 = line2P(t2['p2'], t2['p3'], color='white', width=10)
250
+
251
+ ## Find two intersections on the baseline
252
+
253
+ p1 = lines_intersection(l2, b_line)
254
+ p2 = lines_intersection(l3, b_line)
255
+
256
+ ## Redraw the line-segment with information
257
+
258
+ l4 = line2P(p1, t2['p1'], color = 'black', width=10)
259
+ l5 = line2P(p2, t2['p2'], color = 'black', width=10)
260
+ l3 = line2P(t2['p1'], t2['p2'], color = 'black', width=10)
261
+ ```
262
+
263
+ Feel free to play around the code above to try different design.
264
+
265
+ 6. Try to design/create a shape like the target shape :)
266
+
267
+ """
268
+ )
269
+
270
+ st.divider()
271
+ st.markdown("###### Write your code here")
272
+ ## Code input
273
+ code2 = st_ace(language="python", theme="tomorrow_night_bright", keybinding="vscode", font_size=14, tab_size=4, show_gutter=True, min_lines=10, key="ace2",)
274
+ o1, o2 = st.columns(2)
275
+ if code2:
276
+ ImageDraw.Draw(img).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
277
+ redirected_output = sys.stdout = StringIO()
278
+ try:
279
+ exec(code2)
280
+ result = str(redirected_output.getvalue())
281
+ st.code(result)
282
+ except Exception as e:
283
+ st.code(str(e))
284
+ with o1:
285
+ st.markdown("##### Target Shape:"); target = Image.open('image/T2_t.jpg')
286
+ t2 = target.resize((c_length,c_height))
287
+ ImageDraw.Draw(img_t).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
288
+ img_t.paste(t2); st.image(img_t); st.session_state['imt'] = np.array(img_t)
289
+ with o2:
290
+ st.markdown("##### Output Shape"); st.image(img, caption=''); st.session_state['imo'] = np.array(img)
291
+
292
+ sim = round(uqi(st.session_state['imt'],st.session_state['imo']),4)
293
+ st.write(f"The similarity score between target and output: {sim}")
294
+
295
+
296
+
297
+ with st.expander("Tutorial No.3: Transformation 2, Rotation and Reflection"):
298
+
299
+ st.markdown("We will continues on more transformations that helps us to create shape designs")
300
+ st.markdown(
301
+ """
302
+ 1. Rotation by a point on the canvas:
303
+
304
+ - Copy and past the code below to the code window:
305
+
306
+ ```python
307
+ P1=(100,100); P2=(200,50); P3=(-10,-50)
308
+
309
+ t = triangle_base(P1, P2, P3, 'red')
310
+ t1 = rotation(t,redraw=False, fill='blue') ## Rotation by the origin (0,0), default
311
+ # rotate 90 degree based on a point from the triangle
312
+ t2 = rotation(t, t['p1'], redraw = False, fill = 'yellow')
313
+ # rotate 120 degree based on a point on the canvas
314
+ t3 = rotation(t, (-50, 100), angle=120, redraw=False, fill='orange')
315
+
316
+ ```
317
+
318
+ You should see differernt rotations with different color
319
+ Carefully read the code and comments, figuring out:
320
+ -- What is the parameter that control the point of rotation
321
+ -- what is the parameter that control the degree of rotation
322
+
323
+
324
+ 2. Reflection by a line on the canvas:
325
+
326
+ - Copy and past the code below to the code window:
327
+
328
+ ```python
329
+ P1=(100,100); P2=(200,50); P3=(-10,-50)
330
+
331
+ t = triangle_base(P1, P2, P3, 'red')
332
+
333
+ ## Define different lines
334
+ l1 = line2P(t['p2'],t['p3'], 'green')
335
+ l2 = line2P((0,0),(0,200), 'yellow')
336
+ l3 = line2P((100,0),(200,0), 'orange')
337
+
338
+ ## Reflect by different lines:
339
+ t3 = reflection(t, l1, redraw=False, fill='green')
340
+ t4 = reflection(t, l2, redraw=False, fill='yellow')
341
+ t5 = reflection(t, l3, redraw=False, fill='orange')
342
+ ```
343
+
344
+ You should see differernt reflection with different color
345
+ Carefully read the code and comments, figuring out:
346
+
347
+ -- What is the parameter that control the line of reflection
348
+
349
+
350
+ 3. Translations with for loops
351
+
352
+ Let's review the power of our favourate for-loops!
353
+
354
+ - Copy and past the code below to the code window:
355
+
356
+ ```python
357
+ ## You can define the colors you are using at the beginning
358
+ ## To choose the color, using color picker to get the hex code or RGB values
359
+ B_color = 'white'
360
+ P_color = (11, 129, 11)
361
+
362
+ ## Define an initial triangle
363
+ start = triangle_base((20,50),(20,80),(35,22.3),color=B_color)
364
+ start = rescale_c(start,3,color=B_color)
365
+ # try to reflect 1st time
366
+ a = reflection(start,line2P(start['p1'],start['p2'],P_color),
367
+ redraw=False,color=P_color)
368
+
369
+ ## Looping around
370
+
371
+ for i in range(12):
372
+ a = reflection(a,line2P(a['p2'],a['p3']),redraw=False,color=P_color)
373
+ a = reflection(a,line2P(a['p1'],a['p3']),redraw=False,color=P_color)
374
+ ## After reflection you might want to fine-tune to add on another rotation
375
+ reflection(a,line2P(a['p2'],a['p3'],P_color),redraw=False,color=P_color)
376
+
377
+ ```
378
+
379
+ You might also try some different colors for the flower ---
380
+
381
+ 4. Now, see if you can produce a shape stated in "target shape":
382
+
383
+
384
+
385
+
386
+ """
387
+ )
388
+ st.divider()
389
+ st.markdown("###### Write your code here")
390
+ ## Code input
391
+ code3 = st_ace(language="python", theme="tomorrow_night_bright", keybinding="vscode", font_size=14, tab_size=4, show_gutter=True, min_lines=10, key="ace3",)
392
+ o1, o2 = st.columns(2)
393
+ if code3:
394
+ ImageDraw.Draw(img).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
395
+ redirected_output = sys.stdout = StringIO()
396
+ try:
397
+ exec(code3)
398
+ result = str(redirected_output.getvalue())
399
+ st.code(result)
400
+ except Exception as e:
401
+ st.code(str(e))
402
+ with o1:
403
+ st.markdown("##### Target Shape:"); target = Image.open('image/T3_t.jpg')
404
+ t3 = target.resize((c_length,c_height))
405
+ ImageDraw.Draw(img_t).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
406
+ img_t.paste(t3); st.image(img_t); st.session_state['imt'] = np.array(img_t)
407
+ with o2:
408
+ st.markdown("##### Output Shape"); st.image(img, caption=''); st.session_state['imo'] = np.array(img)
409
+
410
+ sim = round(uqi(st.session_state['imt'],st.session_state['imo']),4)
411
+ st.write(f"The similarity score between target and output: {sim}")
pages/2_Chapter_2 Arcs and Circles.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from io import StringIO
3
+ import streamlit as st
4
+ import numpy as np
5
+ from PIL import Image, ImageDraw, ImageColor
6
+ from canvas import *
7
+ from streamlit_ace import st_ace
8
+ import extra_streamlit_components as stx
9
+ from sewar.full_ref import uqi
10
+ from lines import *
11
+ from triangle import *
12
+ from circle import *
13
+
14
+ st.set_page_config(page_title="How to play Shape Puzzle", page_icon=":notebook:")
15
+
16
+
17
+ with st.sidebar:
18
+ color = st.color_picker('color picker', '#00f900', key='l_c')
19
+ st.write(ImageColor.getrgb(color))
20
+
21
+ st.header("Chapter 2: Arcs and Circles")
22
+ st.write("##")
23
+ st.divider()
24
+
25
+ with st.expander("Tutorial No.1: Circles in different way of drawing"):
26
+
27
+ st.markdown("#### Let's start with circle functions.")
28
+ st.markdown(
29
+ """
30
+ 1. Easy like previously, define or claim the key variables, then call the function to draw a circle.
31
+ Be aware that once the size or circle are larger than our size of canvas, that part would not be shown on the canvas.
32
+
33
+ ```python
34
+ ## Claim the center and radiu
35
+ center = (100, -100)
36
+ radiu = 400
37
+ ## Call the function
38
+ circle_c_r(center, radiu, fill = (201, 30, 30), color = (201, 30, 30))
39
+ ```
40
+ Now, by simply design the center of circles and the radius, you can generate some cool design, for example
41
+
42
+ ```python
43
+ ## Claim the center and radiu
44
+ center = (100, -100)
45
+ radiu = 400
46
+ ## Call the function
47
+ circle_c_r(center, radiu, fill = (201, 30, 30), color = (201, 30, 30))
48
+
49
+ c1 = (150, -80)
50
+ r1 = 150
51
+ circle_c_r(c1, r1, fill = 'white', color = 'white')
52
+ ```
53
+
54
+ 2. Our 2nd circle function, circle_draw():
55
+ Sometimes, we might not be able to "see" the center but rather starting at a point on the canvas,
56
+ with some idea of the 'size' in mind, and draw a circle to meet the starting point.
57
+
58
+ This way of drawing a circle might be more natural for some design
59
+
60
+ - In the code window below, define a point to start and the 'size', i.e. diameter of circle:
61
+
62
+ ```python
63
+ a = (-100, 0) ## the x-axis is -100 and y-axis is 0
64
+ angle = 45 ## 45 degree anti-clock wise
65
+ length = 200 ## length of the drawing
66
+ lineDraw(a, angle, length, width=50) ## then call our lineDraw function to draw the line
67
+ ## We can also specify the width of drawing by passing parameter explicitly.
68
+ ```
69
+
70
+ You should see a slant line-segment in the canvas.
71
+
72
+ 3. Release the power of for-loop:
73
+ The most powerful part of drawing through code is the capability of producing iterative graphs.
74
+ The more detailed instruction about Python for-loops, please check [here](https://www.w3schools.com/python/python_for_loops.asp)
75
+
76
+ - In the code window below, define a startinig point and using for-loop and lineDraw:
77
+
78
+ ```python
79
+ c = (-50,-100) ## The starting point to draw
80
+ lst = [c] ## Create a list for later reference
81
+ for i in range (100): ## Iterate 100 rounds
82
+ l = lineDraw(lst[-1], i*125, 300, (212, 16, 16), width=2) ## Try to figure out what are we doing here?
83
+ lst.append(l['end']) ## add the end-point of the line drawn to the list for the next iteration
84
+ ```
85
+ 4. Now, see if you can produce a shape stated in "target shape":
86
+
87
+ ```python
88
+ s = (0,0) ## The starting point
89
+ n = 8 ##
90
+ lst = [s]
91
+
92
+ #### Start your for-loop here ####
93
+
94
+ #### End of your for-loop ####
95
+ ```
96
+ Having fun!!
97
+ """
98
+ )
99
+ st.divider()
100
+ st.markdown("###### Write your code here")
101
+ ## Code input
102
+ code1 = st_ace(language="python", theme="tomorrow_night_bright", keybinding="vscode", font_size=14, tab_size=4, show_gutter=True, min_lines=10, key="ace",)
103
+ o1, o2 = st.columns(2)
104
+ if code1:
105
+ ImageDraw.Draw(img).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
106
+ redirected_output = sys.stdout = StringIO()
107
+ try:
108
+ exec(code1)
109
+ result = str(redirected_output.getvalue())
110
+ st.code(result)
111
+ except Exception as e:
112
+ st.code(str(e))
113
+ with o1:
114
+ st.markdown("##### Target Shape:"); target = Image.open('image/T1_t.jpg')
115
+ t2 = target.resize((c_length,c_height))
116
+ ImageDraw.Draw(img_t).rectangle([(0, 0), (c_length,c_height)], fill = c_color, outline = c_outline, width=2)
117
+ img_t.paste(t2); st.image(img_t); st.session_state['imt'] = np.array(img_t)
118
+ with o2:
119
+ st.markdown("##### Output Shape"); st.image(img, caption=''); st.session_state['imo'] = np.array(img)
120
+
121
+ sim = round(uqi(st.session_state['imt'],st.session_state['imo']),4)
122
+ st.write(f"The similarity score between target and output: {sim}")
pages/3_Functions.py ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ with st.expander("Line Functions"):
4
+
5
+ st.markdown("##### Line Functions")
6
+ st.divider()
7
+ st.markdown(
8
+ """
9
+ **:red[line2P(start, end, color=(0,0,0), width=1)]**
10
+ - *Draws an line segment between the start and end points.*
11
+
12
+ **PEREMETERS**
13
+
14
+ - **start**: The start point of the line segment. [Data format, tuple], e.g. (100, 200)
15
+ - **end**: The end point of the line segment. [Data format, tuple], e.g. (200, 100)
16
+ - **color**: The color of the line segment. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
17
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
18
+ - **width**: The width of the drawing of the line segment. [Data format, int]
19
+ """)
20
+
21
+ st.divider()
22
+ st.markdown(
23
+ """
24
+ **:red[lineDraw(start, angle, length, color=(0,0,0), width=1)]**
25
+ - *Draws an line segment from a starting point with predetermined angle and length.*
26
+
27
+ **PEREMETERS**
28
+
29
+ - **start**: The start point of the line segment. [Data format, tuple], e.g. (100, 200)
30
+ - **angle**: The angle of direction of the line drawing towards. [Data format, int or float]. For example, starting from
31
+ (0,0) the origin of the canvas and draw a horizental line to the right, the angle would be 0 degree, so angle = 0;
32
+ to draw a vertical line goes up, the angle would be 90 degree, thus angle = 90.
33
+ - **length**: The length of the line drawing. [Data format, int or float]. Warning: the canvas is set up with dimention (700,600),
34
+ so if the lenght of line starting from (0,0) to the right horizentally with length 400, the canvas can only show 350 of the drawing.
35
+ - **color**: The color of the line segment. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
36
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
37
+ - **width**: The width of the drawing of the line segment. [Data format, int]
38
+ """)
39
+
40
+ st.divider()
41
+ st.markdown(
42
+ """
43
+ **:red[lineFunc(x_range, alpha=1, const = 0, color=(0,0,0), width=1)]**
44
+ - *Draws an line segment on a canvas based on its linear equation.*
45
+
46
+ **PEREMETERS**
47
+
48
+ - **x_range**: The range of domain (x-axis) of the linear function. [Data format, tuple], e.g. (100, 200)
49
+ - **alpha**: The gradient (slope) of the linear function. [Data format, int or float].
50
+ - **const**: The y-intecept of the linear funciton. [Data format, int or float].
51
+ - **color**: The color of the line segment. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
52
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
53
+ - **width**: The width of the drawing of the line segment. [Data format, int]
54
+ """)
55
+
56
+ st.divider()
57
+ st.markdown(
58
+ """
59
+ **:red[p2d(start, end)]**
60
+ - *Given two points, return linear data of them.*
61
+
62
+ **PEREMETERS**
63
+
64
+ - **start**: The start point of the line segment. [Data format, tuple], e.g. (100, 200)
65
+ - **end**: The end point of the line segment. [Data format, tuple], e.g. (200, 100)
66
+
67
+ **RETURNS**
68
+
69
+ - **angle**: The angle of the line w.r.t. the positive x-axis;
70
+ - **dist**: The distance between two points, i.e. the length of the line segment;
71
+ - **x_range**: The range of the x-axis of two points;
72
+ - **mid_point**: The midpoint of the line segment between two end points.
73
+ """)
74
+
75
+ st.divider()
76
+ st.markdown(
77
+ """
78
+ **:red[lines_intersection(l1, l2)]**
79
+ - *Given two non-parallel lines, return the point of intesection.*
80
+
81
+ **PEREMETERS**
82
+
83
+ - **l1**: The first line segment. [Data format, line objects], For example, if we created a line by other line function, such as
84
+ l1 = line2P(), the function line2P() will create a python dictionary with data {'start': the start point, 'end': the end point};
85
+ This object can be passed to the lines_intersection() function.
86
+ - **l2**: same as above
87
+
88
+ **RETURNS**
89
+
90
+ - the point of intersection, (x_axis, y_axis).
91
+ """)
92
+
93
+
94
+ with st.expander("Triangle Functions"):
95
+
96
+ st.markdown("##### Triangle Functions")
97
+ st.markdown(
98
+ """
99
+ **:red[triangle_base(p1, p2, p3, fill = None, color=(0,0,0), width=1)]**
100
+ - *Draws a triangle based on three points given.*
101
+
102
+ **PEREMETERS**
103
+
104
+ - **p1 / p2 / p3**: Three points as compolsory parameters of drawing. [Data format, tuple], e.g. (100, 200)
105
+ - **fill**: The color of the shape of triangle (interior area). [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
106
+ the color picker in the slide bar of section of the app. Default value, None, not filling any color.
107
+ - **color**: The color of the edge of the triangle. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
108
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
109
+ - **width**: The width of the drawing of the line segment. [Data format, int]
110
+ """)
111
+
112
+ st.divider()
113
+ st.markdown(
114
+ """
115
+ **:red[triangle_LP(line, p, fill=None, color = (0,0,0))]**
116
+ - *Draws a triangle based on a line-segment and a point out of the line.*
117
+
118
+ **PEREMETERS**
119
+
120
+ - **line**: The line segment. [Data format, line objects], For example, if we created a line by other line function, such as
121
+ l1 = line2P(), the function line2P() will create a python dictionary with data {'start': the start point, 'end': the end point};
122
+ - **p**: The point out of the line-segment for the triangle. [Data format, tuple], e.g. (100, 200)
123
+ - **fill**: The color of the shape of triangle (interior area). [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
124
+ the color picker in the slide bar of section of the app. Default value, None, not filling any color.
125
+ - **color**: The color of the edge of the triangle. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
126
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
127
+ - **width**: The width of the drawing of the line segment. [Data format, int]
128
+ """)
129
+
130
+ st.divider()
131
+ st.markdown(
132
+ """
133
+ **:red[t_center(triangle)]**
134
+ - *Given a triangle object, returns the centers of the triangle object.*
135
+
136
+ **PEREMETERS**
137
+
138
+ - **triangle**: The triangle object drawing from the above two functions. [Data format, dictionary];
139
+
140
+ **RETURNS**
141
+
142
+ - A dictionary of centers of the target triangle.
143
+
144
+ -- 'centroid': the [centroid](https://byjus.com/maths/centroid/) of the triangle.
145
+ """)
146
+
147
+ st.divider()
148
+ st.markdown(
149
+ """
150
+ **:red[rescale_c(shape, alpha = 1, redraw=True, color='black', fill='white', width=1)]**
151
+ - *Given a triangle, rescale the triangle based on the center of the triangle.*
152
+
153
+ **PEREMETERS**
154
+
155
+ - **shape**: The triangle object drawing from the above two functions. [Data format, dictionary];
156
+ - **alpha**: The scaling factor. Default = 1, i.e. same size as the original shape. When alpha > 1, it means enlarge the triangle;
157
+ when 0 < alpha < 1, it means shrink the triangle.
158
+ - **redraw**: The boolean parameter to determine whether to eliminate the original triangle. Default = True, i.e. only keep the newly drawn triangle;
159
+ - **fill**: The color of the shape of triangle (interior area). [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
160
+ the color picker in the slide bar of section of the app. Default value, None, not filling any color.
161
+ - **color**: The color of the edge of the triangle. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
162
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
163
+ - **width**: The width of the drawing of the line segment. [Data format, int]
164
+ """)
165
+
166
+ st.divider()
167
+ st.markdown(
168
+ """
169
+ **:red[rescale_p(shape, point='p1',alpha = 1, redraw=True, color='black', fill='white', width=1)]**
170
+ - *Given a triangle, rescale the triangle based on a vertex on the triangle.*
171
+
172
+ **PEREMETERS**
173
+
174
+ - **shape**: The triangle object drawing from the above two functions. [Data format, dictionary];
175
+ - **point**: The name of the vertex of the triangle object. ('p1', 'p2', or 'p3'). [Data format, string];
176
+ - **alpha**: The scaling factor. Default = 1, i.e. same size as the original shape. When alpha > 1, it means enlarge the triangle;
177
+ when 0 < alpha < 1, it means shrink the triangle.
178
+ - **redraw**: The boolean parameter to determine whether to eliminate the original triangle. Default = True, i.e. only keep the newly drawn triangle;
179
+ - **fill**: The color of the shape of triangle (interior area). [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
180
+ the color picker in the slide bar of section of the app. Default value, None, not filling any color.
181
+ - **color**: The color of the edge of the triangle. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
182
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
183
+ - **width**: The width of the drawing of the line segment. [Data format, int]
184
+ """)
185
+
186
+ st.divider()
187
+ st.markdown(
188
+ """
189
+ **:red[translate_o(shape, vector=(0,0), redraw=True, color='black', fill=None, width=1)]**
190
+ - *Given a triangle, translate the triangle based on a vector from the oringin.*
191
+
192
+ **PEREMETERS**
193
+
194
+ - **shape**: The triangle object drawing from the above two functions. [Data format, dictionary];
195
+ - **vector**: The vector of translation. Default value = (0,0), i.e. no translation;
196
+ - **redraw**: The boolean parameter to determine whether to eliminate the original triangle.
197
+ Default = True, i.e. only keep the newly drawn triangle;
198
+ - **fill**: The color of the shape of triangle (interior area). [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
199
+ the color picker in the slide bar of section of the app. Default value, None, not filling any color.
200
+ - **color**: The color of the edge of the triangle. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
201
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
202
+ - **width**: The width of the drawing of the line segment. [Data format, int]
203
+ """)
204
+
205
+ st.divider()
206
+ st.markdown(
207
+ """
208
+ **:red[translate_p(shape, vector=(100,0), point='p1', redraw=True, color='black', fill=None, width=1)]**
209
+ - *Given a triangle, translate the triangle based on a vector from a vertex of a triangle.*
210
+
211
+ **PEREMETERS**
212
+
213
+ - **shape**: The triangle object drawing from the above two functions. [Data format, dictionary];
214
+ - **vector**: The vector of translation. Default value = (100,0);
215
+ - **point**: The name of the vertex of the triangle object. ('p1', 'p2', or 'p3'). [Data format, string];
216
+ - **redraw**: The boolean parameter to determine whether to eliminate the original triangle.
217
+ Default = True, i.e. only keep the newly drawn triangle;
218
+ - **fill**: The color of the shape of triangle (interior area). [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
219
+ the color picker in the slide bar of section of the app. Default value, None, not filling any color.
220
+ - **color**: The color of the edge of the triangle. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
221
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
222
+ - **width**: The width of the drawing of the line segment. [Data format, int]
223
+ """)
224
+
225
+ st.divider()
226
+ st.markdown(
227
+ """
228
+ **:red[rotation(shape, point=(0,0), angle=90, redraw=True, color='black', fill='white', width=1)]**
229
+ - *Given a triangle, rotate the triangle based on a point on Canvas.*
230
+
231
+ **PEREMETERS**
232
+
233
+ - **shape**: The triangle object drawing from the above two functions. [Data format, dictionary];
234
+ - **point**: The name of the vertex of the triangle object. ('p1', 'p2', or 'p3'). [Data format, string];
235
+ - **angle**: The angle of rotation, clockwise, default value = 90, i.e. 90 degrees;
236
+ - **redraw**: The boolean parameter to determine whether to eliminate the original triangle.
237
+ Default = True, i.e. only keep the newly drawn triangle;
238
+ - **fill**: The color of the shape of triangle (interior area). [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
239
+ the color picker in the slide bar of section of the app. Default value, None, not filling any color.
240
+ - **color**: The color of the edge of the triangle. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
241
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
242
+ - **width**: The width of the drawing of the line segment. [Data format, int]
243
+ """)
244
+
245
+ st.divider()
246
+ st.markdown(
247
+ """
248
+ **:red[reflection(shape, line, redraw=True, color='black', fill='white', width=1)]**
249
+ - *Given a triangle, reflect the triangle based on a line already existed on Canvas.*
250
+
251
+ **PEREMETERS**
252
+
253
+ - **shape**: The triangle object drawing from the above two functions. [Data format, dictionary];
254
+ - **line**: The variable name of the line defined. [Data format, dictionary];
255
+ - **redraw**: The boolean parameter to determine whether to eliminate the original triangle.
256
+ Default = True, i.e. only keep the newly drawn triangle;
257
+ - **fill**: The color of the shape of triangle (interior area). [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
258
+ the color picker in the slide bar of section of the app. Default value, None, not filling any color.
259
+ - **color**: The color of the edge of the triangle. [Data format, tuple], e.g.(255,255,255). The RGB form of color can be extracted from
260
+ the color picker in the slide bar of section of the app. Default value, black, (0,0,0)
261
+ - **width**: The width of the drawing of the line segment. [Data format, int]
262
+ """)
263
+
264
+
pages/4_Gallary.py ADDED
@@ -0,0 +1 @@
 
 
1
+ import streamlit as st
requirements.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ openai==0.27.5
2
+ dotenv==1.0.0
3
+ pandas
4
+ wordcloud==1.9.2
5
+ matplotlib
6
+ plotly==5.15.0
7
+ nltk==3.8.1
8
+ Pillow==9.5.0
9
+ streamlit-ace==0.1.1
10
+ extra-streamlit-components==0.1.56
11
+ streamlit-image-select==0.6.0
12
+ sewar==0.4.6
13
+ shapely==2.0.1
14
+
triangle.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image, ImageDraw
2
+ import math
3
+ import numpy as np
4
+ from canvas import *
5
+
6
+
7
+ def _re_coord(point,x=c_length/2,y=c_height/2):
8
+ return (point[0]+x, y-point[1])
9
+
10
+ def _back_coord(point):
11
+ return (point[0]-c_length/2, c_height/2-point[1])
12
+
13
+ def triangle_base(p1, p2, p3, fill = None, color=(0,0,0),width=1):
14
+ draw.polygon([_re_coord(p1),_re_coord(p2),_re_coord(p3)], fill=fill, outline=color)
15
+ #draw.line([p1, p2], fill=color, width=width, joint=None)
16
+ #draw.line([p2, p3], fill=color, width=width, joint=None)
17
+ #draw.line([p3, p1], fill=color, width=width, joint=None)
18
+ #draw.point([p1,p2,p3], fill=color)
19
+ data = {'p1':p1,
20
+ 'p2':p2,
21
+ 'p3':p3}
22
+ return data
23
+
24
+ def triangle_LP(line, p, fill=None, color = (0,0,0)):
25
+ p1 = _re_coord(line['start'])
26
+ p2 = _re_coord(line['end'])
27
+ p3 = _re_coord(p)
28
+ draw.polygon([p1,p2,p3], fill=fill, outline=color)
29
+ data = {'p1':_back_coord(p1),
30
+ 'p2':_back_coord(p2),
31
+ 'p3':_back_coord(p3)}
32
+ return data
33
+
34
+ def t_center(triangle):
35
+ reshapes = dict(map(lambda x: (x[0], _re_coord(x[1])), triangle.items()))
36
+ p1,p2,p3=reshapes.values()
37
+ p1 = np.asarray(p1);p2 = np.asarray(p2);p3 = np.asarray(p3)
38
+
39
+ centroid_x = (p1[0] + p2[0] + p3[0]) / 3
40
+ centroid_y = (p1[1] + p2[1] + p3[1]) / 3
41
+
42
+ data = {'centroid':_back_coord((centroid_x,centroid_y))}
43
+ return data
44
+
45
+ def rescale_c(shape, alpha = 1, redraw=True, color='black', fill='white',width=1):
46
+ reshapes = dict(map(lambda x: (x[0], _re_coord(x[1])), shape.items()))
47
+
48
+ p1,p2,p3=reshapes.values()
49
+ p1 = np.asarray(p1);p2 = np.asarray(p2);p3 = np.asarray(p3)
50
+ d1 = np.linalg.norm(p2-p3); d2 = np.linalg.norm(p1-p3); d3 = np.linalg.norm(p1-p2)
51
+ dv = np.array([d1,d2,d3])
52
+ pxv = np.array([p1[0],p2[0],p3[0]]); pyv = np.array([p1[1],p2[1],p3[1]])
53
+ c_x = np.dot(dv,pxv)/np.sum(dv); c_y = np.dot(dv,pyv)/np.sum(dv)
54
+ p1n = (p1-np.array([c_x,c_y]))*alpha + np.array([c_x,c_y])
55
+ p2n = (p2-np.array([c_x,c_y]))*alpha + np.array([c_x,c_y])
56
+ p3n = (p3-np.array([c_x,c_y]))*alpha + np.array([c_x,c_y])
57
+ if redraw:
58
+ triangle_base(_back_coord(p1),_back_coord(p2),_back_coord(p3), fill = c_color, color=c_color)
59
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
60
+ else:
61
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
62
+ data = {'p1':_back_coord(tuple(p1n)),
63
+ 'p2':_back_coord(tuple(p2n)),
64
+ 'p3':_back_coord(tuple(p3n))}
65
+ return data
66
+
67
+
68
+ def rescale_p(shape, point='p1',alpha = 1, redraw=True, color='black', fill='white',width=1):
69
+ reshapes = dict(map(lambda x: (x[0], _re_coord(x[1])), shape.items()))
70
+ p1,p2,p3=reshapes.values()
71
+ p1 = np.asarray(p1);p2 = np.asarray(p2); p3 = np.asarray(p3)
72
+ p = _re_coord(shape[point])
73
+ p1n = (p1-p)*alpha + p
74
+ p2n = (p2-p)*alpha + p
75
+ p3n = (p3-p)*alpha + p
76
+ if redraw:
77
+ triangle_base(_back_coord(p1),_back_coord(p2),_back_coord(p3), fill = c_color, color=c_color)
78
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
79
+ else:
80
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
81
+ data = {'p1':_back_coord(tuple(p1n)),
82
+ 'p2':_back_coord(tuple(p2n)),
83
+ 'p3':_back_coord(tuple(p3n))}
84
+ return data
85
+
86
+ def translate_o(shape, vector=(0,0), redraw=True, color='black', fill='white',width=1):
87
+ reshapes = dict(map(lambda x: (x[0], _re_coord(x[1])), shape.items()))
88
+ p1,p2,p3=reshapes.values()
89
+ p1 = np.asarray(p1);p2 = np.asarray(p2);p3 = np.asarray(p3)
90
+ p1n = (p1[0] + vector[0], p1[1]-vector[1])
91
+ p2n = (p2[0] + vector[0], p2[1]-vector[1])
92
+ p3n = (p3[0] + vector[0], p3[1]-vector[1])
93
+ if redraw:
94
+ triangle_base(_back_coord(p1),_back_coord(p2),_back_coord(p3), fill = c_color, color=c_color)
95
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
96
+ else:
97
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
98
+ data = {'p1':_back_coord(tuple(p1n)),
99
+ 'p2':_back_coord(tuple(p2n)),
100
+ 'p3':_back_coord(tuple(p3n))}
101
+ return data
102
+
103
+ def translate_p(shape, vector=(100,0), point='p1', redraw=True, color='black', fill='white',width=1):
104
+ reshapes = dict(map(lambda x: (x[0], _re_coord(x[1])), shape.items()))
105
+ p1,p2,p3=reshapes.values()
106
+ p1 = np.asarray(p1);p2 = np.asarray(p2);p3 = np.asarray(p3)
107
+ vec = np.asarray(vector)-np.asarray(shape[point])
108
+ p1n = (p1[0] + vec[0], p1[1]-vec[1])
109
+ p2n = (p2[0] + vec[0], p2[1]-vec[1])
110
+ p3n = (p3[0] + vec[0], p3[1]-vec[1])
111
+ if redraw:
112
+ triangle_base(_back_coord(p1),_back_coord(p2),_back_coord(p3), fill = c_color, color=c_color)
113
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
114
+ else:
115
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
116
+ data = {'p1':_back_coord(tuple(p1n)),
117
+ 'p2':_back_coord(tuple(p2n)),
118
+ 'p3':_back_coord(tuple(p3n))}
119
+ return data
120
+
121
+ def rotation(shape, point=(0,0),angle=90,redraw=True, color='black', fill='white',width=1):
122
+ c, s = np.cos(np.radians(angle)), np.sin(np.radians(angle))
123
+ R = np.array(((c, -s), (s, c)))
124
+
125
+ reshapes = dict(map(lambda x: (x[0], _re_coord(x[1])), shape.items()))
126
+ p1,p2,p3=reshapes.values()
127
+ p1 = np.asarray(p1);p2 = np.asarray(p2);p3 = np.asarray(p3)
128
+ p = np.asarray(_re_coord(point))
129
+
130
+ p1n = np.matmul(R,p1 - p) + p
131
+ p2n = np.matmul(R,p2 - p) + p
132
+ p3n = np.matmul(R,p3 - p) + p
133
+
134
+ if redraw:
135
+ triangle_base(_back_coord(p1),_back_coord(p2),_back_coord(p3), fill = c_color, color=c_color)
136
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
137
+ else:
138
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
139
+ data = {'p1':_back_coord(tuple(p1n)),
140
+ 'p2':_back_coord(tuple(p2n)),
141
+ 'p3':_back_coord(tuple(p3n))}
142
+ return data
143
+
144
+ def reflection(shape, line, redraw=True, color='black', fill='white',width=1):
145
+
146
+ reshapes_l = dict(map(lambda x: (x[0], _re_coord(x[1])), line.items()))
147
+ l1,l2 = reshapes_l.values()
148
+ l1 = np.asarray(l1); l2=np.asarray(l2)
149
+ dx=l2[0]-l1[0]; dy = l2[1]-l1[1]
150
+
151
+ if dx != 0:
152
+ slope = dy/dx
153
+ angle = np.arctan(slope)
154
+ c, s = np.cos(angle), np.sin(angle)
155
+ R = np.array(((c, s), (-s, c)))
156
+ nR = np.array(((c, -s), (s, c)))
157
+ else:
158
+ R = np.array(((1, 0), (0, -1)))
159
+ nR = np.array(((-1, 0), (0, 1)))
160
+
161
+ ref = np.array(((1, 0), (0, -1)))
162
+
163
+ reshapes = dict(map(lambda x: (x[0], _re_coord(x[1])), shape.items()))
164
+ p1,p2,p3=reshapes.values()
165
+ p1 = np.asarray(p1);p2 = np.asarray(p2);p3 = np.asarray(p3)
166
+
167
+ p1n = np.matmul(nR,np.matmul(ref, np.matmul(R,p1 - l1))) + l1
168
+ p2n = np.matmul(nR,np.matmul(ref, np.matmul(R,p2 - l1))) + l1
169
+ p3n = np.matmul(nR,np.matmul(ref, np.matmul(R,p3 - l1))) + l1
170
+
171
+ if redraw:
172
+ triangle_base(_back_coord(p1),_back_coord(p2),_back_coord(p3), fill = c_color, color=c_color)
173
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
174
+ else:
175
+ triangle_base(_back_coord(p1n),_back_coord(p2n),_back_coord(p3n), fill = fill, color=color)
176
+ data = {'p1':_back_coord(tuple(p1n)),
177
+ 'p2':_back_coord(tuple(p2n)),
178
+ 'p3':_back_coord(tuple(p3n))}
179
+ return data