calculate the distance matrix from the center given a matrix of size n

Question:

let’s say I have a matrix of size n (an odd number that’s not 1) and I want to calculate the distance each entry is from the center. For example, if n = 2, then the matrix is 5 by 5 and to find the center of the matrix you would do..

import numpy as np
import math
center = math.floor(5/2)
Matrix[math.floor(5/2)][math.floor(5/2)] = 0

The center is zero because the distance to itself is 0. my approach is make the center like the origin of a coordinate plane and treat each of the 25 “squares” (5 by 5 matrix) as a dot in the center of each square and then calculate the euclidean distance that dot is from the center. visually:
enter image description here

my idea so far..

Matrix = [[0 for x in range(n)] for y in range(n)] #initialize the n by n matrix
for i in range(0, n):
    for j in range(0, n):
        Matrix[i][j] = ...

or is there a better way to find the distance matrix?

the output should be symmetric and for a n = 5 matrix it would be

Matrix
[[2.82843, 2.23607, 2, 2.23607, 2.82843],
 [2.23607, 1.41421, 1, 1.41421, 2.23607],
 [2, 1, 0, 1, 2],
 [2.23607, 1.41421, 1, 1.41421, 2.23607],
 [2.82843, 2.23607, 2, 2.23607, 2.82843]]

TIA

Asked By: Aystealthy

||

Answers:

The answer is Pythagoras famous theorem: https://www.mathsisfun.com/pythagoras.html
For a cell at (i,j) you’ll need the (x,y) offset to the center cell – then apply Pythagoras theorem to compute distance to that cell…

def pythag(a, b):
    return math.sqrt(a*a + b*b)

n = 5
import math
center = math.floor(n/2)
for i in range(0, n):
    for j in range(0, n):
      dist = pythag(i-center, j-center)
      print(dist)

Here’s a repl with the code: https://repl.it/@powderflask/DizzyValuableQuark

Answered By: powderflask

Try to avoid loops when using numpy:

x_size, y_size = 5, 5
x_arr, y_arr = np.mgrid[0:x_size, 0:y_size]
cell = (2, 2)
dists = np.sqrt((x_arr - cell[0])**2 + (y_arr - cell[1])**2)
Answered By: PMende

For a built-in option without numpy, and where you can shift the origin:

import math

def dist(n, shift=(0,0)):
    sx,sy = shift
    return [[math.hypot(min(i, n-i), min(j, n-j)) for j in range(-sx,n-sx)] for i in range(-sy,n-sy)]

print(*dist(5, (2,2)), sep='n') # shift origin to center
print(*dist(5), sep='n')        # no shift

Output:

[2.8284271247461903, 2.23606797749979, 2.0, 2.23606797749979, 2.8284271247461903]
[2.23606797749979, 1.4142135623730951, 1.0, 1.4142135623730951, 2.23606797749979]
[2.0, 1.0, 0.0, 1.0, 2.0]
[2.23606797749979, 1.4142135623730951, 1.0, 1.4142135623730951, 2.23606797749979]
[2.8284271247461903, 2.23606797749979, 2.0, 2.23606797749979, 2.8284271247461903]

[0.0, 1.0, 2.0, 2.0, 1.0]
[1.0, 1.4142135623730951, 2.23606797749979, 2.23606797749979, 1.4142135623730951]
[2.0, 2.23606797749979, 2.8284271247461903, 2.8284271247461903, 2.23606797749979]
[2.0, 2.23606797749979, 2.8284271247461903, 2.8284271247461903, 2.23606797749979]
[1.0, 1.4142135623730951, 2.23606797749979, 2.23606797749979, 1.4142135623730951]
Answered By: Rodrigo Rodrigues

Here is the code that utilizes numpy broadcasting and will help you:

def generate_distance_matrix(center: Tuple[float, float], size: Tuple[int, int]) -> np.array:
    width, height = size
    x_c, y_c = center

    dist_array_w = (np.arange(width) - x_c)**2
    dist_array_h = (np.arange(height)[np.newaxis, :] - y_c)**2

    dist_matrix = np.zeros(size)
    dist_matrix += dist_array_w
    dist_matrix += dist_array_h.T

    return np.sqrt(dist_matrix)
Answered By: Daniil Masalskiy
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.