I am interested in finding the average spacing between objects on a directional basis. I did my best to minimally implement this in Python and to conform to PEP8.
I try to explain what I'm doing in the code comments. The problem I want to solve is to find the average spacing between circles of known radius and locations (in my application, these locations are irregular) on a directional basis. For example, what is the average spacing between these circles in the x, diagonal, and y directions?
import numpy as np
# I have a set of x and y coordinates describing the
# locations of objects
px = np.array([0, 0, 0, 10, 10, 10, 20, 20, 20])
py = np.array([0, 10, 20, 0, 10, 20, 0, 10, 20])
# Each object is a circle with known radius size
point_diameter = 2
# I'll put my answers here
spacing = {}
# The challenge is to calculate the average spacing per point on a directional
# basis, e.g., what is the average distance between points in the direction
# of 45 degrees?
# To do this, I define a function to check if points are alligned in a
# direction
def check_alligned(direction, p1x, p1y, p2x, p2y):
# Since the points have some wisdth, I need to check the "edge cases"
# as well as the centerlines.
tolerance = 0.2
pr = point_diameter / 2
for offsetx1 in [-1, 0, 1]:
for offsetx2 in [-1, 0, 1]:
for offsety1 in [-1, 0, 1]:
for offsety2 in [-1, 0, 1]:
# The scheme is to check if the direction leads to the object x or y location.
# I chose or to handle cases where the x or y difference is zero.
distance = distance_between([p1x + pr*offsetx1,
p1y + pr*offsety1],
[p2x + pr*offsetx2,
p2y + pr*offsety2])
if abs(p1x + distance * np.cos(np.radians(direction)) - p2x) <= tolerance or abs(p1y + distance * np.sin(np.radians(direction)) - p2y) <= tolerance:
return True
return False
def distance_between(v1, v2):
return np.sqrt( (v1[0] - v2[0])**2 + (v1[1] - v2[1])**2)
# Initial Smallest Spacing - use to find if we get to a spacing in the loop
# and record the smallest one
ISP = 9e4
# Iterate through directions to calculate average distance in each direction.
# Directions go counterclockwise and x points in the direction of 0 degrees.
for direction in [0, 60, 45, 90]:
# These are a running sum and counter of 1st nearest neighbor spacings
# that are less than an initial smallest spacing value. They are used
# to calculate the average spacing in each direction.
total_spacing = 0.
space_count = 0
# Look through every point
for ii in range(px.size):
smallest_spacing = ISP
# and every other point except ones we've already checked
for jj in range(px.size - ii - 1):
# If the jj point is not in the same line as the
# ii point along this diretion, skip it
idx2 = ii + jj + 1
if check_alligned(direction, px[ii], py[ii], px[idx2], py[idx2]):
space = np.sqrt((px[ii]-px[idx2])**2 +
(py[ii] - py[idx2])**2)
if space < smallest_spacing:
smallest_spacing = space
# Record a distance if it is less than the initial
# smallest spacing
if smallest_spacing != ISP:
total_spacing += smallest_spacing
space_count += 1
# record the average spacing in this direction
if space_count:
spacing[direction] = total_spacing / space_count
else:
spacing[direction] = 0.
print spacing