我正在开发一个程序(用Python),该程序涉及将正方形切成更小的块。 用户必须输入一个“代码”,程序将自动将其转换为每个单独矩形的坐标。每个矩形还有一个与之关联的值。
到目前为止,我想出了以下代码:
1 # the entire square
0.5;0.5 # square split in half from top to bottom
1:0.5,0.5 # square split in half from side to side
0.5;0.5:0.15,0.35,0.5 # square split in half from top to bottom, with the right side being further subdivided
;
处理从左到右的划分,:
+,
处理从上到下的细分。
我遇到的问题是,用当前的方法不可能表示相对简单的东西:
我能想到的解决这个问题的唯一方法是某种递归算法,它将执行某种代码并在提示时生成坐标。优先考虑的是尽可能保持用户友好,因为这些代码可能会被输入多次,并且令人困惑/冗长的代码将违背其目的(可以只输入嵌套的
dict
/list
)。我仍然无法理解这样的事情是如何运作的......
另一种解决方案是使用某种
tkinter
GUI。我将它用于我的项目并作为此代码的输入,因此某种交互式框(例如那些中间有滑块的网站,它会向您显示之前和之后?)也可以工作。
程序的这一部分处理将日语汉字(汉字)拆分为组成部分部首/部分。大多数汉字已经可以用我的解决方案表示,但还有很多不能!字符显示在
tkinter Canvas
对象上,每个部首后面绘制有矩形。用户用鼠标选择一些部首(我已经完成了这部分)。
正如我所提到的,每个矩形都有一个分配的值,并且有一个默认值。这意味着在我尝试转换为坐标之前,我使用嵌套列表来存储值:
[[0.5,[[1,1]]],[0.5,[[0.15,1],[0.35,1],[0.5,1]]]] # generated from the fourth example
^ assigmed value ^ ^ ^
坐标是根据
Canvas
物体的边长计算的。
虽然不是绝对必要的,但在代码中/与 tkinter 小部件组合这些矩形的方法将非常有用,因为某些部首可能具有奇怪的形状(如 L),甚至包裹所有内容(如口)。
这有点难以解释,所以请尝试一下示例或给我更多要编码的形状:
import tkinter as tk
def cut(direction, cuts, left, right, top, bottom):
if direction == "v":
start, end = left, right
elif direction == "h":
start, end = top, bottom
else:
raise ValueError("Direction must be vertical/horizontal ('v' or 's')")
total = 0
last_loc = 0
for fraction, sub_cuts in cuts:
total += fraction
loc = start + (end-start)*total
# Calculate the (x1,y1), (x2,y2) of the line that will be displayed
if direction == "v":
x1 = x2 = loc
y1, y2 = top, bottom
cut("h", sub_cuts, last_loc, loc, top, bottom) # recursively cut
elif direction == "h":
y1 = y2 = loc
x1, x2 = left, right
cut("v", sub_cuts, left, right, last_loc, loc) # recursively cut
canvas.create_line(x1, y1, x2, y2, fill="white") # create the line
last_loc += loc
WIDTH = 400
HEIGHT = 400
root = tk.Tk()
canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="black")
canvas.pack()
# No cuts
cuts = []
# Cut it vertically 50%
cuts = [(0.5,[])]
# Cut it 50% vertically and for the left small rectangle cut it horizontally 50%
cuts = [(0.5, [(0.5,[])])]
# Cut it 50% vertically and leave the left part.
# The right part gets cut twice more at 15% and at (15+35)%
cuts = [(0.5,[]), (0.5, [(0.15,[]), (0.35,[])])]
# Cut it vertically right at the end (does nothing - except now we can cut horizontally)
# Then cut it hotizontally at 50%. The top part gets cut vertically at 50%
cuts = [(1, [(0.5, [(0.5, [])])])]
# Cut 50% vertically and do nothing right the left part.
# The right part (other 50% of the total area) gets cut horizontally at 50%
# And the top part of that gets cuts 50% vertically again
cuts = [(0.5,[]), (0.5,[(0.5,[(0.5,[])])])]
cut("v", cuts, 0, WIDTH, 0, HEIGHT)
首先,我注意到您先进行(多次)垂直切割,然后进行(多次)水平切割。您可以在垂直和水平切割之间交替进行。 因此,对于每次切割,我的列表都会存储一个分数以及相反方向的进一步切割列表。
因此,如果您想将其切成三份(垂直),您可以使用
[(1/3,[]), (1/3,[])]
(以 1/3 的比例进行 2 次切割,并使用空列表表示不再进行切割)。
要将其切成三份(水平),您可以使用相同的但将其包裹在
[(1, <list from previous example>)]
内。这会在最右边进行切割(基本上什么都不做),然后水平切割。
正如我所说,这有点难以解释,但请随时给我更多示例,我可以转换这些示例,以便您能够理解。