1

I have a huge number of points that represent centers of gravity of rectangles. My task is to create a 3D numpy array of a shape (len(x_values) * len(y_values), 4, 2) that would contain [x,y] coordinates of all 4 tops of those rectangles.

Example:

  • center of gravity of the first rectangle is [4.0, 5.0]
  • rectangle width (always a constant) = 2.0
  • rectangle height (always a constant) = 3.0
  • the first set of points (tops of a rectangle) in the numpy array would be:
[[[3.  3.5]     # 4.0 - 2.0/2, 5.0 - 3.0/2 ... first top
  [3.  6.5]     # 4.0 - 2.0/2, 5.0 + 3.0/2 ... second top
  [5.  6.5]     # 4.0 + 2.0/2, 5.0 + 3.0/2 ... third top
  [5.  3.5]]    # 4.0 + 2.0/2, 5.0 - 3.0/2 ... fourth top
  
  ...           # other points
]  

I wrote this code:

import numpy as np
import random


# Just an example of points that represent centers of gravity of rectangles; 500 000 in total
x_values = [random.uniform(0, 10) for _ in range(1000)]
y_values = [random.uniform(0, 10) for _ in range(500)]

WIDTH = 2.0
HEIGHT = 3.0

my_points = np.zeros(shape=(len(x_values) * len(y_values), 4, 2), dtype=np.float64)

ii = 0
for y in y_values:
    for x in x_values:
        # [x, y] ... center of gravity of a rectangle
        my_points[ii][0][0] = x - WIDTH*0.5
        my_points[ii][0][1] = y - HEIGHT*0.5
        my_points[ii][1][0] = x - WIDTH*0.5
        my_points[ii][1][1] = y + HEIGHT*0.5
        my_points[ii][2][0] = x + WIDTH*0.5
        my_points[ii][2][1] = y + HEIGHT*0.5
        my_points[ii][3][0] = x + WIDTH*0.5
        my_points[ii][3][1] = y - HEIGHT*0.5
        ii += 1

However, this approach is really slow for huge number of points. Is there a better and faster way how to fill the array?

1 Answer 1

2

The speedup comes from vectorizing the assignment and eliminating the python loop.

my_points = np.empty(shape=(len(x_values) * len(y_values), 4, 2), dtype=np.float64)

x = np.tile(x_values, len(y_values))
y = np.repeat(y_values, len(x_values))

my_points[:,1,0] = my_points[:,0,0] = x - WIDTH*0.5
my_points[:,3,1] = my_points[:,0,1] = y - HEIGHT*0.5
my_points[:,2,1] = my_points[:,1,1] = y + HEIGHT*0.5
my_points[:,3,0] = my_points[:,2,0] = x + WIDTH*0.5
Sign up to request clarification or add additional context in comments.

2 Comments

Amazing solution! Thanks a lot!
heh, probably a million times faster :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.