Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小康2022
tkintertools
提交
66cfd335
tkintertools
项目概览
小康2022
/
tkintertools
10 个月 前同步成功
通知
132
Star
13
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
Wiki
0
Wiki
分析
仓库
DevOps
代码片段
项目成员
Pages
tkintertools
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
代码片段
代码片段
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
66cfd335
编写于
5月 26, 2023
作者:
小康2022
👍
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
version 2.6.2-dev
上级
1eb6827c
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
487 addition
and
120 deletion
+487
-120
CHANGELOG.md
CHANGELOG.md
+8
-0
README.md
README.md
+4
-4
test.py
test.py
+164
-113
tkintertools/__init__.py
tkintertools/__init__.py
+1
-2
tkintertools/__main__.py
tkintertools/__main__.py
+1
-1
tkintertools/tools_3d.py
tkintertools/tools_3d.py
+309
-0
未找到文件。
CHANGELOG.md
浏览文件 @
66cfd335
ChangeLog/更新日志
=================
[2.6.2] - 2023-05-26
--------------------
### Features/新增
-
[X] Added
`tkintertools`
sub-module
`tools_3d`
to support drawing 3D graphics
新增
`tkintertools`
子模块
`tools_3d`
以支持绘制3d图形
### Optimized/优化
[2.6.1] - 2023-05-21
...
...
README.md
浏览文件 @
66cfd335
...
...
@@ -13,7 +13,7 @@
<img
src=
"https://img.shields.io/badge/License-Mulan PSL v2-green"
alt=
"License"
/>
</a>
<a
href=
"./CHANGELOG.md"
>
<img
src=
"https://img.shields.io/badge/ChangeLog-2023/05/2
1
-orange"
alt=
"ChangeLog"
/>
<img
src=
"https://img.shields.io/badge/ChangeLog-2023/05/2
6
-orange"
alt=
"ChangeLog"
/>
</a>
<a
href=
"./TODO.md"
>
<img
src=
"https://img.shields.io/badge/ToDos-10-yellow"
alt=
"ToDos"
/>
...
...
@@ -56,11 +56,11 @@ pip install tkintertools
### Development version/开发版本
*
Version/版本 : 2.6.
1
*
Release Date/发布日期 : 2023/05/2
1
*
Version/版本 : 2.6.
2
*
Release Date/发布日期 : 2023/05/2
6
```
pip install tkintertools-dev==2.6.
1
pip install tkintertools-dev==2.6.
2
```
这个是作者正在开发的版本,有新功能,但不能保证稳定,bug 可能会比较多。
...
...
test.py
浏览文件 @
66cfd335
""" Test program """
from
math
import
cos
,
pi
from
random
import
randint
from
tkinter
import
TclError
,
messagebox
from
random
import
randint
,
sample
from
tkinter
import
Event
,
TclError
,
messagebox
import
tkintertools
as
tkt
def
colorful
(
ind
=
0
,
# type: int
color
=
[
None
,
'#F1F1F1'
]
# type: list[str | None]
):
# type: (...) -> None
""" Change color randomly and Gradiently """
if
not
ind
:
color
[
0
],
color
[
1
]
=
color
[
1
],
'#%06X'
%
randint
(
0
,
1
<<
24
)
color
=
tkt
.
color
(
color
,
ind
)
color_
=
tkt
.
color
(
color
)
canvas_doc
.
configure
(
bg
=
color
)
for
widget
in
canvas_main
.
_widget
:
widget
.
color_fill
[
0
],
widget
.
color_text
[
0
]
=
color
,
color_
widget
.
state
()
root
.
after
(
20
,
colorful
,
0
if
ind
>=
1
else
ind
+
0.01
)
def
draw
(
ind
=
0
,
n
=
200
):
# type: (int, int) -> None
""" Draw a sphere """
canvas_graph
.
create_oval
(
canvas_graph
.
rx
*
(
500
-
ind
/
3
),
canvas_graph
.
ry
*
(
300
-
ind
/
3
),
canvas_graph
.
rx
*
(
600
+
ind
),
canvas_graph
.
ry
*
(
400
+
ind
),
fill
=
''
if
ind
else
'white'
,
outline
=
tkt
.
color
((
'#000000'
,
'#FFFFFF'
),
cos
(
ind
*
pi
/
2
/
n
)),
width
=
3
)
if
ind
<
n
:
root
.
after
(
10
,
draw
,
ind
+
1
)
def
update
(
ind
=
0
):
# type: (int) -> None
""" Load the progress """
bar
.
load
(
ind
)
if
ind
<
1
:
root
.
after
(
2
,
update
,
ind
+
0.0002
)
def
shutdown
():
# type: () -> None
""" Ask before quit """
if
messagebox
.
askyesno
(
'Test program'
,
'Do you want to exit the test program?'
):
root
.
quit
()
root
=
tkt
.
Tk
(
'tkintertools'
,
1280
,
720
,
shutdown
=
shutdown
)
root
.
minsize
(
640
,
360
)
canvas_main
=
tkt
.
Canvas
(
root
,
1280
,
720
,
0
,
0
)
canvas_doc
=
tkt
.
Canvas
(
root
,
1280
,
720
,
-
1280
,
0
)
canvas_graph
=
tkt
.
Canvas
(
root
,
1280
,
720
,
1280
,
0
)
tkt
.
Button
(
canvas_main
,
10
,
660
,
200
,
50
,
text
=
'Doc'
,
command
=
lambda
:
(
tkt
.
move
(
root
,
canvas_main
,
1280
*
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
root
,
canvas_doc
,
1280
*
canvas_doc
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
tkt
.
Button
(
canvas_main
,
1070
,
660
,
200
,
50
,
text
=
'Image'
,
command
=
lambda
:
(
tkt
.
move
(
root
,
canvas_main
,
-
1280
*
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
root
,
canvas_graph
,
-
1280
*
canvas_graph
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
tkt
.
Button
(
canvas_doc
,
1070
,
660
,
200
,
50
,
text
=
'Back'
,
command
=
lambda
:
(
tkt
.
move
(
root
,
canvas_main
,
-
1280
*
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
root
,
canvas_doc
,
-
1280
*
canvas_doc
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
tkt
.
Button
(
canvas_graph
,
10
,
660
,
200
,
50
,
text
=
'Back'
,
command
=
lambda
:
(
tkt
.
move
(
root
,
canvas_main
,
1280
*
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
root
,
canvas_graph
,
1280
*
canvas_graph
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
tkt
.
Text
(
canvas_main
,
10
,
10
,
625
,
300
,
radius
=
20
,
text
=
(
'Centered and Rounded TextBox'
,
'Click to Input'
),
justify
=
'center'
)
tkt
.
Text
(
canvas_main
,
645
,
10
,
625
,
300
,
text
=
(
'Right-leaning TextBox'
,
'Click to Input'
),
cursor
=
' _'
)
tkt
.
Entry
(
canvas_main
,
10
,
320
,
300
,
35
,
radius
=
10
,
text
=
(
'Rounded InputBox'
,
'Click to Input'
),
justify
=
'center'
)
tkt
.
Entry
(
canvas_main
,
970
,
320
,
300
,
35
,
text
=
(
'InputBox'
,
'Click to Input'
),
show
=
'•'
)
tkt
.
Button
(
canvas_main
,
10
,
365
,
300
,
40
,
radius
=
10
,
text
=
'Rounded Button'
,
command
=
lambda
:
tkt
.
move
(
canvas_main
,
label_1
,
0
,
-
170
*
canvas_main
.
ry
,
500
,
mode
=
'flat'
))
tkt
.
Button
(
canvas_main
,
1070
,
365
,
200
,
40
,
text
=
'Button'
,
command
=
lambda
:
tkt
.
move
(
canvas_main
,
label_2
,
0
,
-
170
*
canvas_main
.
ry
,
500
,
mode
=
'smooth'
))
tkt
.
CheckButton
(
canvas_main
,
10
,
415
,
35
,
radius
=
10
,
text
=
'Rounded CheckButton'
)
tkt
.
CheckButton
(
canvas_main
,
1235
,
415
,
35
,
value
=
True
,
text
=
'CheckButton'
,
justify
=
'left'
)
label_1
=
tkt
.
Label
(
canvas_main
,
235
,
730
,
400
,
150
,
radius
=
20
,
text
=
'Rounded Label
\n
move mode: flat'
)
label_2
=
tkt
.
Label
(
canvas_main
,
645
,
730
,
400
,
150
,
text
=
'Label
\n
move mode: smooth'
)
button_1
=
tkt
.
Button
(
canvas_doc
,
1070
,
10
,
200
,
50
,
text
=
'Colorful'
,
command
=
lambda
:
(
button_1
.
set_live
(
False
),
colorful
()))
button_2
=
tkt
.
Button
(
canvas_graph
,
10
,
10
,
200
,
50
,
text
=
'Draw'
,
command
=
lambda
:
(
button_2
.
set_live
(
False
),
draw
()))
load
=
tkt
.
Button
(
canvas_main
,
540
,
365
,
200
,
40
,
text
=
'Load'
,
command
=
lambda
:
(
update
(),
load
.
set_live
(
False
)))
bar
=
tkt
.
Progressbar
(
canvas_main
,
320
,
320
,
640
,
35
)
font_chooseer
=
tkt
.
Button
(
canvas_main
,
500
,
465
,
280
,
40
,
text
=
'Select a Font'
,
command
=
lambda
:
tkt
.
askfont
(
root
,
lambda
font
:
canvas_main
.
itemconfigure
(
font_chooseer
.
text
,
font
=
font
)))
canvas_doc
.
create_text
(
15
,
360
,
text
=
tkt
.
__doc__
,
font
=
(
tkt
.
FONT
,
14
),
anchor
=
'w'
)
try
:
canvas_graph
.
create_image
(
1150
,
130
,
image
=
tkt
.
PhotoImage
(
'tkintertools.png'
))
except
TclError
:
print
(
'
\033
[31mLoad tkintertools.png Error
\033
[0m'
)
root
.
mainloop
()
from
tkintertools
import
constants
as
cnt
from
tkintertools
import
tools_3d
as
t3d
class
Application
:
def
__init__
(
self
):
self
.
root
=
tkt
.
Tk
(
'tkintertools'
,
1280
,
720
,
shutdown
=
self
.
shutdown
)
self
.
root
.
minsize
(
640
,
360
)
self
.
canvas_main
=
tkt
.
Canvas
(
self
.
root
,
1280
,
720
,
0
,
0
)
self
.
canvas_doc
=
tkt
.
Canvas
(
self
.
root
,
1280
,
720
,
-
1280
,
0
)
self
.
canvas_graph
=
tkt
.
Canvas
(
self
.
root
,
1280
,
720
,
1280
,
0
)
self
.
canvas_3d
=
tkt
.
Canvas
(
self
.
root
,
1280
,
720
,
1280
,
0
)
self
.
canvas_main_init
()
self
.
canvas_doc_init
()
self
.
canvas_graph_init
()
self
.
canvas_3d_init
()
self
.
root
.
mainloop
()
def
shutdown
(
self
):
# type: () -> None
""" Ask before quit """
if
messagebox
.
askyesno
(
'Test program'
,
'Do you want to exit the test program?'
):
self
.
root
.
quit
()
def
colorful
(
self
,
ind
=
0
,
# type: int
color
=
[
None
,
'#F1F1F1'
]
# type: list[str | None]
):
# type: (...) -> None
""" Change color randomly and Gradiently """
if
not
ind
:
color
[
0
],
color
[
1
]
=
color
[
1
],
'#%06X'
%
randint
(
0
,
1
<<
24
)
color
=
tkt
.
color
(
color
,
ind
)
color_
=
tkt
.
color
(
color
)
self
.
canvas_doc
.
configure
(
bg
=
color
)
for
widget
in
self
.
canvas_main
.
_widget
:
widget
.
color_fill
[
0
],
widget
.
color_text
[
0
]
=
color
,
color_
widget
.
state
()
self
.
root
.
after
(
20
,
self
.
colorful
,
0
if
ind
>=
1
else
ind
+
0.01
)
def
draw
(
self
,
ind
=
0
,
n
=
200
):
# type: (int, int) -> None
""" Draw a sphere """
self
.
canvas_graph
.
create_oval
(
self
.
canvas_graph
.
rx
*
(
500
-
ind
/
3
),
self
.
canvas_graph
.
ry
*
(
300
-
ind
/
3
),
self
.
canvas_graph
.
rx
*
(
600
+
ind
),
self
.
canvas_graph
.
ry
*
(
400
+
ind
),
fill
=
''
if
ind
else
'white'
,
outline
=
tkt
.
color
((
'#000000'
,
'#FFFFFF'
),
cos
(
ind
*
pi
/
2
/
n
)),
width
=
3
)
if
ind
<
n
:
self
.
root
.
after
(
10
,
self
.
draw
,
ind
+
1
)
def
update
(
self
,
ind
=
0
):
# type: (int) -> None
""" Load the progress """
self
.
bar
.
load
(
ind
)
if
ind
<
1
:
self
.
root
.
after
(
2
,
self
.
update
,
ind
+
0.0002
)
def
canvas_main_init
(
self
):
tkt
.
Button
(
self
.
canvas_main
,
10
,
660
,
200
,
50
,
text
=
'Doc'
,
command
=
lambda
:
(
tkt
.
move
(
self
.
root
,
self
.
canvas_main
,
1280
*
self
.
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
self
.
root
,
self
.
canvas_doc
,
1280
*
self
.
canvas_doc
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
tkt
.
Button
(
self
.
canvas_main
,
1070
,
660
,
200
,
50
,
text
=
'Image'
,
command
=
lambda
:
(
tkt
.
move
(
self
.
root
,
self
.
canvas_main
,
-
1280
*
self
.
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
self
.
root
,
self
.
canvas_graph
,
-
1280
*
self
.
canvas_graph
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
tkt
.
Text
(
self
.
canvas_main
,
10
,
10
,
625
,
300
,
radius
=
20
,
text
=
(
'Centered and Rounded TextBox'
,
'Click to Input'
),
justify
=
'center'
)
tkt
.
Text
(
self
.
canvas_main
,
645
,
10
,
625
,
300
,
text
=
(
'Right-leaning TextBox'
,
'Click to Input'
),
cursor
=
' _'
)
tkt
.
Entry
(
self
.
canvas_main
,
10
,
320
,
300
,
35
,
radius
=
10
,
text
=
(
'Rounded InputBox'
,
'Click to Input'
),
justify
=
'center'
)
tkt
.
Entry
(
self
.
canvas_main
,
970
,
320
,
300
,
35
,
text
=
(
'InputBox'
,
'Click to Input'
),
show
=
'•'
)
tkt
.
Button
(
self
.
canvas_main
,
10
,
365
,
300
,
40
,
radius
=
10
,
text
=
'Rounded Button'
,
command
=
lambda
:
tkt
.
move
(
self
.
canvas_main
,
label_1
,
0
,
-
170
*
self
.
canvas_main
.
ry
,
500
,
mode
=
'flat'
))
tkt
.
Button
(
self
.
canvas_main
,
1070
,
365
,
200
,
40
,
text
=
'Button'
,
command
=
lambda
:
tkt
.
move
(
self
.
canvas_main
,
label_2
,
0
,
-
170
*
self
.
canvas_main
.
ry
,
500
,
mode
=
'smooth'
))
tkt
.
CheckButton
(
self
.
canvas_main
,
10
,
415
,
35
,
radius
=
10
,
text
=
'Rounded CheckButton'
)
tkt
.
CheckButton
(
self
.
canvas_main
,
1235
,
415
,
35
,
value
=
True
,
text
=
'CheckButton'
,
justify
=
'left'
)
label_1
=
tkt
.
Label
(
self
.
canvas_main
,
235
,
730
,
400
,
150
,
radius
=
20
,
text
=
'Rounded Label
\n
move mode: flat'
)
label_2
=
tkt
.
Label
(
self
.
canvas_main
,
645
,
730
,
400
,
150
,
text
=
'Label
\n
move mode: smooth'
)
load
=
tkt
.
Button
(
self
.
canvas_main
,
540
,
365
,
200
,
40
,
text
=
'Load'
,
command
=
lambda
:
(
self
.
update
(),
load
.
set_live
(
False
)))
self
.
bar
=
tkt
.
Progressbar
(
self
.
canvas_main
,
320
,
320
,
640
,
35
)
font_chooseer
=
tkt
.
Button
(
self
.
canvas_main
,
500
,
465
,
280
,
40
,
text
=
'Select a Font'
,
command
=
lambda
:
tkt
.
askfont
(
self
.
root
,
lambda
font
:
self
.
canvas_main
.
itemconfigure
(
font_chooseer
.
text
,
font
=
font
)))
def
canvas_doc_init
(
self
):
tkt
.
Button
(
self
.
canvas_doc
,
1070
,
660
,
200
,
50
,
text
=
'Back'
,
command
=
lambda
:
(
tkt
.
move
(
self
.
root
,
self
.
canvas_main
,
-
1280
*
self
.
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
self
.
root
,
self
.
canvas_doc
,
-
1280
*
self
.
canvas_doc
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
button_1
=
tkt
.
Button
(
self
.
canvas_doc
,
1070
,
10
,
200
,
50
,
text
=
'Colorful'
,
command
=
lambda
:
(
button_1
.
set_live
(
False
),
self
.
colorful
()))
self
.
canvas_doc
.
create_text
(
15
,
360
,
text
=
tkt
.
__doc__
,
font
=
(
cnt
.
FONT
,
14
),
anchor
=
'w'
)
def
canvas_graph_init
(
self
):
tkt
.
Button
(
self
.
canvas_graph
,
1070
,
660
,
200
,
50
,
text
=
'3D'
,
command
=
lambda
:
(
tkt
.
move
(
self
.
root
,
self
.
canvas_graph
,
-
1280
*
self
.
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
self
.
root
,
self
.
canvas_3d
,
-
1280
*
self
.
canvas_graph
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
tkt
.
Button
(
self
.
canvas_graph
,
10
,
660
,
200
,
50
,
text
=
'Back'
,
command
=
lambda
:
(
tkt
.
move
(
self
.
root
,
self
.
canvas_main
,
1280
*
self
.
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
self
.
root
,
self
.
canvas_graph
,
1280
*
self
.
canvas_graph
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
button_2
=
tkt
.
Button
(
self
.
canvas_graph
,
10
,
10
,
200
,
50
,
text
=
'Draw'
,
command
=
lambda
:
(
button_2
.
set_live
(
False
),
self
.
draw
()))
try
:
self
.
canvas_graph
.
create_image
(
1150
,
130
,
image
=
tkt
.
PhotoImage
(
'tkintertools.png'
))
except
TclError
:
print
(
'
\033
[31mLoad tkintertools.png Error
\033
[0m'
)
def
canvas_3d_init
(
self
):
self
.
create_3d
()
tkt
.
Button
(
self
.
canvas_3d
,
10
,
660
,
200
,
50
,
text
=
'Back'
,
command
=
lambda
:
(
tkt
.
move
(
self
.
root
,
self
.
canvas_graph
,
1280
*
self
.
canvas_main
.
rx
,
0
,
500
,
mode
=
'rebound'
),
tkt
.
move
(
self
.
root
,
self
.
canvas_3d
,
1280
*
self
.
canvas_graph
.
rx
,
0
,
500
,
mode
=
'rebound'
)))
def
spin
(
self
,
event
):
# type: (Event, list[float]) -> None
dx
,
dy
=
event
.
x
-
self
.
pos
[
0
],
event
.
y
-
self
.
pos
[
1
]
self
.
pos
=
[
event
.
x
,
event
.
y
]
for
item
in
self
.
lst_3ditems
:
item
.
rotate
(
0
,
-
dy
/
100
,
dx
/
100
)
for
item
in
self
.
lst_3ditems
:
item
.
update
(
500
,
640
,
360
)
def
create_3d
(
self
):
self
.
lst_3ditems
=
[]
# type: list[t3d.Cuboid]
self
.
pos
=
[
0
,
0
]
# type: list[float]
def
modify
(
event
):
self
.
pos
=
[
event
.
x
,
event
.
y
]
for
_
in
range
(
10
):
cube
=
t3d
.
Cuboid
(
self
.
canvas_3d
,
*
sample
(
range
(
-
200
,
200
),
3
),
*
sample
(
range
(
50
,
100
),
3
))
cube
.
draw
(
500
,
640
,
360
)
self
.
lst_3ditems
.
append
(
cube
)
x
,
y
,
z
=
sample
(
range
(
-
200
,
200
),
3
)
tetr
=
t3d
.
Tetrahedron
(
self
.
canvas_3d
,
*
[(
x
+
randint
(
-
100
,
100
),
y
+
randint
(
-
100
,
100
),
z
+
randint
(
-
100
,
100
))
for
_
in
range
(
4
)])
tetr
.
draw
(
500
,
640
,
360
)
self
.
lst_3ditems
.
append
(
tetr
)
self
.
canvas_3d
.
focus_set
()
self
.
canvas_3d
.
bind
(
'<Button-1>'
,
lambda
event
:
modify
(
event
))
self
.
canvas_3d
.
bind
(
'<B1-Motion>'
,
self
.
spin
)
if
__name__
==
'__main__'
:
Application
()
tkintertools/__init__.py
浏览文件 @
66cfd335
...
...
@@ -37,7 +37,6 @@ if sys.version_info < (3, 7): # Version Check
from
.__main__
import
(
Button
,
Canvas
,
CheckButton
,
Entry
,
Label
,
PhotoImage
,
Progressbar
,
SetProcessDpiAwareness
,
Singleton
,
Text
,
Tk
,
Toplevel
,
askfont
,
color
,
move
,
text
)
from
.constants
import
*
__author__
=
'Xiaokang2022<2951256653@qq.com>'
__version__
=
'2.6.1'
...
...
@@ -49,5 +48,5 @@ __all__ = [
# Tool Classes
'PhotoImage'
,
'Singleton'
,
# Tool Functions
'move'
,
'text'
,
'color'
,
'askfont'
,
'SetProcessDpiAwareness'
'move'
,
'text'
,
'color'
,
'askfont'
,
'SetProcessDpiAwareness'
,
]
tkintertools/__main__.py
浏览文件 @
66cfd335
""" Main File """
import
math
# 数学
函数
import
math
# 数学
支持
import
sys
# DPI 兼容
import
tkinter
# 基础模块
from
fractions
import
Fraction
# 图片缩放
...
...
tkintertools/tools_3d.py
0 → 100644
浏览文件 @
66cfd335
""" 3D support """
import
math
# 数学支持
import
statistics
# 数据统计
import
tkinter
# 基础模块
from
typing
import
Iterable
# 类型提示
import
tkintertools
# 类型提示
def
_cross
(
matrix
,
# type: list[list[float]]
vector
,
# type: list[float]
):
# type: (...) -> list[float]
""" 转换矩阵 """
for
i
in
range
(
3
):
matrix
[
0
][
i
]
=
sum
(
matrix
[
i
][
j
]
*
vector
[
j
]
for
j
in
range
(
3
))
return
matrix
[
0
]
class
Point
:
""" 点 """
def
__init__
(
self
,
coords
):
# type: (list[float]) -> None
self
.
coords
=
list
(
coords
)
# 利用列表引用
def
translate
(
self
,
dx
=
0
,
dy
=
0
,
dz
=
0
):
# type: (float, float, float) -> Point
""" 平移 """
self
.
coords
[
0
]
+=
dx
self
.
coords
[
1
]
+=
dy
self
.
coords
[
2
]
+=
dz
return
self
def
rotate
(
self
,
dx
=
0
,
dy
=
0
,
dz
=
0
):
# type: (float, float, float) -> Point
""" 旋转 """
sa
,
sb
,
sc
=
math
.
sin
(
dx
),
math
.
sin
(
dy
),
math
.
sin
(
dz
)
ca
,
cb
,
cc
=
math
.
cos
(
dx
),
math
.
cos
(
dy
),
math
.
cos
(
dz
)
M
=
[[
cc
*
cb
,
cc
*
sb
*
sa
-
sc
*
ca
,
cc
*
sb
*
ca
+
sc
*
sa
],
[
sc
*
cb
,
sc
*
sb
*
sa
+
cc
*
ca
,
sc
*
sb
*
ca
-
cc
*
sa
],
[
-
sb
,
cb
*
sa
,
cb
*
ca
]]
self
.
coords
[
0
],
self
.
coords
[
1
],
self
.
coords
[
2
]
=
_cross
(
M
,
self
.
coords
)
return
self
def
project
(
self
,
distance
):
# type: (float) -> list[float]
""" 投影 """
try
:
coefficient
=
distance
/
(
distance
-
self
.
coords
[
0
])
except
:
return
[
distance
,
distance
]
return
[
self
.
coords
[
1
]
*
coefficient
,
self
.
coords
[
2
]
*
coefficient
]
class
Line
:
""" 线 """
def
__init__
(
self
,
x1
,
# type: float
y1
,
# type: float
z1
,
# type: float
x2
,
# type: float
y2
,
# type: float
z2
,
# type: float
):
# type: (...) -> None
self
.
coords
=
[[
x1
,
y1
,
z1
],
[
x2
,
y2
,
z2
]]
self
.
points
=
[
Point
(
coord
)
for
coord
in
self
.
coords
]
def
translate
(
self
,
dx
=
0
,
dy
=
0
,
dz
=
0
):
# type: (float, float, float) -> Line
""" 平移 """
for
point
in
self
.
points
:
point
.
translate
(
dx
,
dy
,
dz
)
return
self
def
rotate
(
self
,
dx
=
0
,
dy
=
0
,
dz
=
0
):
# type: (float, float, float) -> Line
""" 旋转 """
for
point
in
self
.
points
:
point
.
rotate
(
dx
,
dy
,
dz
)
return
self
def
project
(
self
,
distance
):
# type: (float) -> list[list[float]]
""" 投影 """
return
[
point
.
project
(
distance
)
for
point
in
self
.
points
]
class
Side
:
""" 面 """
def
__init__
(
self
,
*
coords
):
# type: (list[float]) -> None
self
.
coords
=
list
(
coords
)
self
.
lines
=
[
Line
(
*
coords
[
ind
-
1
],
*
coords
[
ind
])
for
ind
in
range
(
len
(
coords
))]
def
translate
(
self
,
dx
=
0
,
dy
=
0
,
dz
=
0
):
# type: (float, float, float) -> Side
""" 平移 """
for
line
in
self
.
lines
:
line
.
translate
(
dx
,
dy
,
dz
)
return
self
def
rotate
(
self
,
dx
=
0
,
dy
=
0
,
dz
=
0
):
# type: (float, float, float) -> Side
""" 旋转 """
for
line
in
self
.
lines
:
line
.
rotate
(
dx
,
dy
,
dz
)
return
self
def
project
(
self
,
distance
):
# type: (float) -> list[list[list[float]]]
""" 投影 """
return
[
line
.
project
(
distance
)
for
line
in
self
.
lines
]
class
Geometry
:
""" 几何体 """
def
__init__
(
self
,
canvas
,
*
sides
):
# type: (tkintertools.Canvas, Side) -> None
"""
`canvas`: 显示的画布
\n
`size`: 平面类`Side`
\n
"""
self
.
canvas
=
canvas
self
.
coords
=
[]
# type: list[list[float]]
self
.
sides
=
[]
# type: list[Side]
self
.
items
=
[]
# type: list[tkinter._CanvasItemId]
if
sides
:
self
.
append
(
*
sides
)
def
translate
(
self
,
dx
=
0
,
dy
=
0
,
dz
=
0
):
# type: (float, float, float) -> None
""" 平移 """
for
side
in
self
.
sides
:
side
.
translate
(
dx
,
dy
,
dz
)
def
rotate
(
self
,
dx
=
0
,
dy
=
0
,
dz
=
0
):
# type: (float, float, float) -> None
""" 旋转 """
for
side
in
self
.
sides
:
side
.
rotate
(
dx
,
dy
,
dz
)
def
center
(
self
):
# type: () -> tuple[float, float, float]
""" 几何中心 """
# NOTE: 对凹面几何体无效
data
=
list
(
zip
(
*
self
.
coords
))
# 转置
x_c
=
statistics
.
mean
(
data
[
0
])
y_c
=
statistics
.
mean
(
data
[
1
])
z_c
=
statistics
.
mean
(
data
[
2
])
return
x_c
,
y_c
,
z_c
def
append
(
self
,
*
sides
):
# type: (Side) -> None
""" 添加面 """
for
side
in
sides
:
for
line
in
side
.
lines
:
for
point
in
line
.
points
:
if
point
not
in
self
.
coords
:
self
.
coords
.
append
(
point
)
self
.
sides
.
append
(
side
)
def
update
(
self
,
distance
,
dx
=
0
,
dy
=
0
):
# type: (float, float, float) -> None
""" 更新几何体 """
c
=
0
for
side
in
self
.
sides
:
coords
=
side
.
project
(
distance
)
for
coord
in
coords
:
k
=
[]
for
lst
in
coord
:
if
dx
or
dy
:
lst
[
0
]
+=
640
lst
[
1
]
+=
360
k
.
append
(
lst
[
0
])
k
.
append
(
lst
[
1
])
self
.
canvas
.
coords
(
self
.
items
[
c
],
k
)
c
+=
1
def
draw
(
self
,
distance
,
dx
=
0
,
dy
=
0
):
# type: (float, float, float) -> None
""" 绘制 """
for
side
in
self
.
sides
:
coords
=
side
.
project
(
distance
)
for
coord
in
coords
:
if
dx
or
dy
:
for
lst
in
coord
:
lst
[
0
]
+=
dx
lst
[
1
]
+=
dy
self
.
items
.
append
(
self
.
canvas
.
create_polygon
(
*
coord
,
outline
=
'black'
))
class
Cuboid
(
Geometry
):
""" 长方体 """
def
__init__
(
self
,
canvas
,
# type: tkintertools.Canvas
x
,
# type: float
y
,
# type: float
z
,
# type: float
length
,
# type: float
width
,
# type: float
height
,
# type: float
):
# type: (...) -> None
"""
`canvas`: 父画布
\n
`x`: 左上角x坐标
\n
`y`: 左上角y坐标
\n
`z`: 左上角z坐标
\n
`length`: 长度
\n
`width`: 宽度
\n
`height`: 高度
\n
"""
self
.
canvas
=
canvas
self
.
coords
=
[[
x
+
l
,
y
+
w
,
z
+
h
]
for
l
in
(
0
,
length
)
for
w
in
(
0
,
width
)
for
h
in
(
0
,
height
)]
self
.
sides
=
[
Side
(
self
.
coords
[
0
],
self
.
coords
[
1
],
self
.
coords
[
3
],
self
.
coords
[
2
]),
Side
(
self
.
coords
[
0
],
self
.
coords
[
1
],
self
.
coords
[
5
],
self
.
coords
[
4
]),
Side
(
self
.
coords
[
0
],
self
.
coords
[
2
],
self
.
coords
[
6
],
self
.
coords
[
4
]),
Side
(
self
.
coords
[
1
],
self
.
coords
[
3
],
self
.
coords
[
7
],
self
.
coords
[
5
]),
Side
(
self
.
coords
[
2
],
self
.
coords
[
3
],
self
.
coords
[
7
],
self
.
coords
[
6
]),
Side
(
self
.
coords
[
4
],
self
.
coords
[
5
],
self
.
coords
[
7
],
self
.
coords
[
6
]),
]
self
.
items
=
[]
# type: list[tkinter._CanvasItemId]
class
Tetrahedron
(
Geometry
):
""" 四面体 """
def
__init__
(
self
,
canvas
,
# type: tkintertools.Canvas
p1
,
# type: Iterable[float]
p2
,
# type: Iterable[float]
p3
,
# type: Iterable[float]
p4
,
# type: Iterable[float]
):
# type: (...) -> None
"""
`canvas`: 父画布
\n
`p1`: 第一个顶点
\n
`p2`: 第二个顶点
\n
`p3`: 第三个顶点
\n
`p4`: 第四个顶点
\n
"""
self
.
canvas
=
canvas
self
.
coords
=
[
list
(
p1
),
list
(
p2
),
list
(
p3
),
list
(
p4
)]
self
.
sides
=
[
Side
(
p1
,
p2
,
p3
),
Side
(
p1
,
p2
,
p4
),
Side
(
p1
,
p3
,
p4
),
Side
(
p2
,
p3
,
p4
),
]
self
.
items
=
[]
# type: list[tkinter._CanvasItemId]
ORIGIN
=
Point
((
0
,)
*
3
)
""" 原点 """
LINE_X
=
Line
(
0
,
0
,
0
,
1
,
0
,
0
)
""" X 轴单位直线 """
LINE_Y
=
Line
(
0
,
0
,
0
,
0
,
1
,
0
)
""" Y 轴单位直线 """
LINE_Z
=
Line
(
0
,
0
,
0
,
0
,
0
,
1
)
""" Z 轴单位直线 """
SIDE_YZ
=
Side
((
0
,
1
,
1
),
(
0
,
1
,
-
1
),
(
0
,
-
1
,
-
1
),
(
0
,
-
1
,
1
))
""" 垂直 X 轴单位平面 """
SIDE_ZX
=
Side
((
1
,
0
,
1
),
(
1
,
0
,
-
1
),
(
-
1
,
0
,
-
1
),
(
-
1
,
0
,
1
))
""" 垂直 Y 轴单位平面 """
SIDE_XY
=
Side
((
1
,
1
,
0
),
(
1
,
-
1
,
0
),
(
-
1
,
-
1
,
0
),
(
-
1
,
1
,
0
))
""" 垂直 Z 轴单位平面 """
# class Ellipsoid:
# """ 椭球体 """
# def __init__(
# self,
# x, # type: float
# y, # type: float
# z, # type: float
# length, # type: float
# width, # type: float
# height # type: float
# ): # type: (...) -> None
# self.coords = [[x+l, y+w, z+h]
# for l in (0, length)
# for w in (0, width)
# for h in (0, height)]
# self.points = [Point(coord) for coord in self.coords]
# def translate(self, dx=0, dy=0, dz=0): # type: (float, float, float) -> None
# """ 平移 """
# for point in self.points:
# point.translate(dx, dy, dz)
# def rotate(self, dx=0, dy=0, dz=0): # type: (float, float, float) -> None
# """ 旋转 """
# for point in self.points:
# point.rotate(dx, dy, dz)
# # type: (float) -> tuple[list[float], list[float]]
# def project(self, distance):
# """ 投影 """
# coefficient = distance/(distance - self.coords[0])
# return [self.coords[1]*coefficient, self.coords[2]*coefficient]
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录