Spaces:
Sleeping
Sleeping
Upload 23 files
Browse files- app.py +108 -0
- canvas.py +13 -0
- circle.py +34 -0
- image/T1.jpg +0 -0
- image/T1_t.jpg +0 -0
- image/T2_1.jpg +0 -0
- image/T2_t.jpg +0 -0
- image/T3_t.jpg +0 -0
- image/TriangleCrash.png +0 -0
- image/TriangleFox.png +0 -0
- image/TriangleHole.png +0 -0
- image/TrianglePolygon.png +0 -0
- image/archillect.png +0 -0
- image/archillect.pngZone.Identifier +4 -0
- img.png +0 -0
- img_t.png +0 -0
- lines.py +61 -0
- pages/1_Chapter_1 Lines and Triangles.py +411 -0
- pages/2_Chapter_2 Arcs and Circles.py +122 -0
- pages/3_Functions.py +264 -0
- pages/4_Gallary.py +1 -0
- requirements.txt +14 -0
- triangle.py +179 -0
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.pngZone.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
|