Placement of squares on the Cartesian plane and development of their X, Y-coordinates based on the serial number

A bunch of guys and me from work tried to wrap my head around this problem, but could not find a clean and effective mathematical way to solve this problem. There he is:

Given the standard Cartesian plane and the sequence of images (all squares and the same size, we just say, for example, 1 unit), how do we arrange them so that they are spiral around the origin (0, 0) of the plane in the upper left corner. But, more specifically, if you specify the number 25, for example (the 25th square in the sequence), what will be the X, Y coordinates?

enter image description here

I hope this rough image helps explain the sequence. The very first square to be placed in the grid will be red, then blue, yellow, purple, green, black, brown, etc. Around, as the dots show.

We hoped that for this there was a "relatively simple mathematical formula", but perhaps this is wishful thinking.

+4
source share
3 answers

(In the editor: I added a second function that allows you to get the Cartesian coordinate version directly.)

, . , , , , . , 8 . 1. , y, - . , , . Python:

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)

(x, y) (i, j), , , :

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 -1 ), , :

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)

1-16:

>>> 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)

:

>>> coordinates(1000000)
(500, 1)

, 1000x1000.

, tkinter:

enter image description here

+1

( ) . "" .

, . :

  • .

, , .

, 4 . ( "".) .

:

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

Assuming you are using indexing based on 1, you can use the following algorithm to find your answer (not sure if a closed form solution exists).

The idea behind this is to find which layer you are on (how far your x or y is from 0). Then find which quadrant you are in. Then find out which side you are on, then find out the coordinates.

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)
0
source

Source: https://habr.com/ru/post/1598985/


All Articles