进行用户友好的输入,将正方形细分为坐标

问题描述 投票:0回答:1

我正在开发一个程序(用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

Crude representation of examples above drawn with MS Paint

;
处理从左到右的划分,
:
+
,
处理从上到下的细分。

我遇到的问题是,用当前的方法不可能表示相对简单的东西:

Impossible to represent figures

我能想到的解决这个问题的唯一方法是某种递归算法,它将执行某种代码并在提示时生成坐标。优先考虑的是尽可能保持用户友好,因为这些代码可能会被输入多次,并且令人困惑/冗长的代码将违背其目的(可以只输入嵌套的

dict
/
list
)。我仍然无法理解这样的事情是如何运作的......

另一种解决方案是使用某种

tkinter
GUI。我将它用于我的项目并作为此代码的输入,因此某种交互式框(例如那些中间有滑块的网站,它会向您显示之前和之后?)也可以工作。

干杯!

注0:

程序的这一部分处理将日语汉字(汉字)拆分为组成部分部首/部分。大多数汉字已经可以用我的解决方案表示,但还有很多不能!字符显示在

tkinter Canvas
对象上,每个部首后面绘制有矩形。用户用鼠标选择一些部首(我已经完成了这部分)。

注1:

正如我所提到的,每个矩形都有一个分配的值,并且有一个默认值。这意味着在我尝试转换为坐标之前,我使用嵌套列表来存储值:

[[0.5,[[1,1]]],[0.5,[[0.15,1],[0.35,1],[0.5,1]]]] # generated from the fourth example
          ^ assigmed value ^        ^       ^

坐标是根据

Canvas
物体的边长计算的。

注2:

虽然不是绝对必要的,但在代码中/与 tkinter 小部件组合这些矩形的方法将非常有用,因为某些部首可能具有奇怪的形状(如 L),甚至包裹所有内容(如口)。

python python-3.x tkinter cjk kanji
1个回答
0
投票

这有点难以解释,所以请尝试一下示例或给我更多要编码的形状:

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>)]
内。这会在最右边进行切割(基本上什么都不做),然后水平切割。

正如我所说,这有点难以解释,但请随时给我更多示例,我可以转换这些示例,以便您能够理解。

© www.soinside.com 2019 - 2024. All rights reserved.