Reputation: 96
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:
[[[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?
Upvotes: 1
Views: 862
Reputation: 30579
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
Upvotes: 2