一群男人和我自己都在试图解决这个问题,但是找不到一个干净有效的数学方法来解决这个问题。这是:
给定一个标准的笛卡尔平面和一系列图像(所有方形和相同的尺寸,我们只说1个单位)我们如何以它们围绕原点旋转的方式组织它们( 0,0)飞机的左上角。但更具体地说,如果给出数字25(例如序列中的第25个方格),它的X,Y坐标是什么?
希望这张原始图像有助于解释序列。放置在网格上的第一个正方形将是红色,然后是蓝色,黄色,紫色,绿色,黑色,棕色,然后如点所示。
我们希望是否有相对"这个简单的数学公式,但也许这是一厢情愿的想法。
答案 0 :(得分:1)
我之前的回答(现在降级到修订历史)是一个递归的解决方案。以下是我称之为" cyclic"溶液
我们的想法是围绕一个正方形进行多次旋转。在任何给定的指数:
通过跟踪正方形,侧面和侧面的距离,我们可以索引每个点。
我们通过绘制4条相等的线来绕过一个正方形。 (称他们为#34;段"。)我们在第一段的中间开始每一次革命。
例如:
革命1是一个大小为0的正方形,长度为1的段:
O OO
O OO OO OO
革命2是一个大小为4的正方形,长度为3的段:
O OOOO OOOO
OO OO OOO OOO OOOO
OOO OOO OOOO OOOO OOOO
O OOOO OOOO OOOO OOOO
革命3是一个大小为16的正方形,长度为5的段:
O OOOOOO OOOOOO
OOOO OOOO OOOOO OOOOO OOOOOO
OOOO OOOO OOOOO OOOOO OOOOOO
OOOOO OOOOO OOOOOO OOOOOO OOOOOO
OOOOO OOOOO OOOOOO OOOOOO OOOOOO
O OOOOOO OOOOOO OOOOOO OOOOOO
下面是Python中的一个实现。
import math
def makeSquare(main_index, offset_size):
step_index = int(math.sqrt(main_index))/2 # How many revolutions have we made?
last_square = int(math.pow(step_index*2,2)) # Whats the largest square less than main_index?
segment_length = (2 * step_index) + 1 # How long is the side of the square we've made so far? The segment length is 1 more than that.
main_index = main_index + step_index + 1 # Skip ahead so we start in the middle of the right side instead of the top. We do some modulo stuff below to wrap around.
segment_index = (main_index - last_square) / segment_length # Which segment are we on?
dot_index = main_index - segment_index*segment_length - last_square # How far along the segment are we?
draw_functions = [
lambda i, size: [size, size - i], # Draw the right side of a square
lambda i, size: [size - i, 0 ], # Draw the bottom of a square
lambda i, size: [0, i ], # Draw the left side of a square
lambda i, size: [i, size ], # Draw the top of a square
]
x, y = draw_functions[segment_index % 4](dot_index % (4 * segment_length), segment_length)
return [ x + offset_size - step_index - 1, y + offset_size - step_index - 1]
# Print the points to the console in sequence
import time, os
step = 4
points = [makeSquare(i, step) for i in range(int(math.pow(step*2,2)))]
board = [[" " for x in range(step*2)] for x in range(step*2)]
for p in range(len(points)):
print
print p, "------------------"
board[step*2-1 - points[p][1]][points[p][0]] = "O" # Do some coordinate wrangling so we have normal X and Y
print (os.linesep).join([''.join(row) for row in board])
time.sleep(.1)
答案 1 :(得分:1)
(编辑:我添加了第二个函数,可以直接获得笛卡尔坐标版本。)
在我头部爆炸之前,我已经走了这么远。它是闭合形式,它给出了百万分之一平方的坐标,而不需要将它们一个接一个地放在一个循环中。写下来不会给出一个很好的公式,但你可以写成一个8件的分段定义公式。答案以1为基础的网格坐标给出。第一个坐标指示您在y轴的右侧或左侧有多少个方格,第二个坐标显示向上或向下的距离。从这些数字可以比较容易地例如得到左上角的笛卡尔坐标。我用Python实现了它:
CSV.foreach(File.path("month.csv")) do |row|
dateper=row[0].split(',')[0]
p DateTime.strptime(dateper,"%m/%d/%y %I:%M:%S %p %z").strftime("%s")
end
要从(i,j)网格坐标获得左上角的(x,y)笛卡尔坐标,可以使用以下函数,该函数具有可选的宽度参数以允许非单位正方形:
from math import sqrt, ceil
def coordinates(m):
n = ceil(sqrt(m)/2) #shell number
i = m - 4*(n-1)**2 #index in shell
if i <= n:
return (n,-i)
elif i <= 2*n-1:
return (2*n - i, -n)
elif i <= 3*n - 1:
return (2*n - 1 - i, -n)
elif i <= 4*n - 2:
return (-n, -4*n + 1 + i)
elif i <= 5*n - 2:
return (-n, -4*n + 2 + i)
elif i <= 6*n - 3:
return (-6*n + 2 + i, n)
elif i <= 7*n - 3:
return (-6*n + 3 + i,n)
else:
return (n, 8*n -3 - i)
可以直接获取左上角的笛卡尔坐标,而无需先通过网格坐标。由此产生的公式涉及较少的案例(因为我不需要从1直接跳到-1,反之亦然)虽然我在答案中保留了两个公式,因为在很多方面,网格视角更自然:
def cartesianFromGrid(i,j,w = 1):
x = w * (i if i < 0 else i - 1)
y = w * (j if j > 0 else j + 1)
return (x,y)
1-16的输出:
def cartCoordinates(m):
n = ceil(sqrt(m)/2) #shell number
i = m - 4*(n-1)**2 #index in shell
if i <= n:
return (n-1,-i+1)
elif i <= 3*n - 1:
return (2*n - 1 - i, -n + 1)
elif i <= (5*n - 2):
return (-n, -4*n + 2 + i)
elif i <= 7*n - 3:
return (-6*n + 2 + i, n)
else:
return (n-1, 8 * n - 3 - i)
万一你想知道:
>>> for n in range(1,17):
print(n, ': grid coords =', coordinates(n),
'Cartesian =',cartesianFromGrid(*coordinates(n)))
1 : grid coords = (1, -1) Cartesian = (0, 0)
2 : grid coords = (-1, -1) Cartesian = (-1, 0)
3 : grid coords = (-1, 1) Cartesian = (-1, 1)
4 : grid coords = (1, 1) Cartesian = (0, 1)
5 : grid coords = (2, -1) Cartesian = (1, 0)
6 : grid coords = (2, -2) Cartesian = (1, -1)
7 : grid coords = (1, -2) Cartesian = (0, -1)
8 : grid coords = (-1, -2) Cartesian = (-1, -1)
9 : grid coords = (-2, -2) Cartesian = (-2, -1)
10 : grid coords = (-2, -1) Cartesian = (-2, 0)
11 : grid coords = (-2, 1) Cartesian = (-2, 1)
12 : grid coords = (-2, 2) Cartesian = (-2, 2)
13 : grid coords = (-1, 2) Cartesian = (-1, 2)
14 : grid coords = (1, 2) Cartesian = (0, 2)
15 : grid coords = (2, 2) Cartesian = (1, 2)
16 : grid coords = (2, 1) Cartesian = (1, 1)
这最后一个答案是有道理的,因为百万分之一的正方形是1000x1000正方形网格的顶点。
我使用上面的方法在tkinter画布小部件上放置彩色方块:
答案 2 :(得分:0)
假设您正在使用基于1的索引,您可以使用以下算法来查找答案(不确定是否存在封闭的表单解决方案)。
这背后的想法是找到你所在的层(你的x或y距离0有多远)。然后找到你所在的象限。然后找出你所在的那一侧,然后找出坐标。
get_coords(n)
layer = 1
while (n > 3 * layer * layer + (layer+1)*(layer+1))
++layer
layer_ind = n - 3 * (layer - 1) * (layer - 1) - layer * layer
if (layer_ind < 2 * layer + 1) # in bottom right
if (layer_ind <= layer + 1)
return (layer, - layer_ind + 1)
else
return (2 * layer + 1 - layer_ind, -layer)
else if ((layer_ind - 2 * layer - 1)/(2 * layer - 1) < 1) # bottom left
layer_ind = layer_ind - 2 * layer - 1
if (layer_ind <= layer)
return (-layer_ind+1, -layer+1)
else
return (-layer+1, -2*layer + 1 + layer_ind)
else if ((layer_ind - 2 * layer - 1)/(2 * layer - 1) < 2) # top left
layer_ind = layer_ind - 4 * layer
if (layer_ind <= layer)
return (-layer+1, layer_ind)
else
return (layer_ind - 2 * layer, layer)
else # top right
layer_ind = layer_ind - 6 * layer + 1
if (layer_ind <= layer)
return (layer_ind-1, layer)
else
return (layer-1, 2 * layer - layer_ind)