Another incarnation which scales well in terms of using real projected coordinates rather than those centered about an origin, is given below. The difference is that you can specify an 'origin' and a 'destination' and the differences in the coordinates are used rather than the actual coordinates themselves.
You can use the following to either determine the angle that a line is directed towards relative to the x-axis or as an azimuth relative to north. In this case, the origin and destination would be the start and end of the line.
Alternately, you can pick a point from an origin feature and get the direction to one of a destination features points. The attached would have be incorporated into a larger script to select the origin point from the origin features and the same for the destination feature. You get the idea I hope (kind of like the Near tool, which could also be swung into service if you have the appropriate license level.
Anyway, here is the code followed by some results for a 0,0 origin and points located at compass points within root(2) of the origin. The 'demo' function is written verbosely so you can see the construction.
def line_dir(orig, dest, fromNorth=False):
"""Direction of a line given 2 points
: orig, dest - two points representing the start and end of a line.
: fromNorth - True or False gives angle relative to x-axis)
:Notes:
:
"""
orig = np.asarray(orig)
dest = np.asarray(dest)
dx, dy = dest - orig
ang = np.degrees(np.arctan2(dy, dx))
if fromNorth:
ang = np.mod((450.0 - ang), 360.)
return ang
def demo(xc=0, yc=0, fromNorth=True):
""" run the demo with the data below """
p0 = np.array([xc, yc])
p1 = p0 + [-1, 1]
p2 = p0 + [0, 1]
p3 = p0 + [1, 1]
p4 = p0 + [1, 0]
p5 = p0 + [1, -1]
p6 = p0 + [0, -1]
p7 = p0 + [-1, -1]
p8 = p0 + [-1, 0]
od = [[p0, p1], [p0, p2], [p0, p3], [p0, p4],
[p0, p5], [p0, p6], [p0, p7], [p0, p8]]
for pair in od:
orig, dest = pair
ang = line_dir(orig, dest, fromNorth=fromNorth)
if fromNorth:
dir = "From N."
else:
dir = "From x-axis"
args = [orig, dest, dir, ang]
print("orig: {}: dest: {!s:<8} {}: {!s:>6}".format(*args))
if __name__ == "__main__":
"""Main section... """
xc = 300000
yc = 5025000
demo(xc, yc, fromNorth = True)
Some results with using the two sample origins.
Note! This can only be used for projected coordinates.
orig: [0 0]: dest: [-1 1] From N.: 315.0
orig: [0 0]: dest: [0 1] From N.: 0.0
orig: [0 0]: dest: [1 1] From N.: 45.0
orig: [0 0]: dest: [1 0] From N.: 90.0
orig: [0 0]: dest: [ 1 -1] From N.: 135.0
orig: [0 0]: dest: [ 0 -1] From N.: 180.0
orig: [0 0]: dest: [-1 -1] From N.: 225.0
orig: [0 0]: dest: [-1 0] From N.: 270.0
orig: [ 300000 5025000]: dest: [ 299999 5025001] From N.: 315.0
orig: [ 300000 5025000]: dest: [ 300000 5025001] From N.: 0.0
orig: [ 300000 5025000]: dest: [ 300001 5025001] From N.: 45.0
orig: [ 300000 5025000]: dest: [ 300001 5025000] From N.: 90.0
orig: [ 300000 5025000]: dest: [ 300001 5024999] From N.: 135.0
orig: [ 300000 5025000]: dest: [ 300000 5024999] From N.: 180.0
orig: [ 300000 5025000]: dest: [ 299999 5024999] From N.: 225.0
orig: [ 300000 5025000]: dest: [ 299999 5025000] From N.: 270.0