def GetAnglesPolyline(polyline, closed=False):
 points = polyline[:, 0]
 if closed:
  a = np.roll(points, 1, axis=0)
  b = points
  c = np.roll(points, (-1), axis=0)
 else:
  a = points[0:(-2)]
  b = points[1:(-1)]
  c = points[2:]
 ab = (b - a)
 cb = (b - c)
 dot = np.sum((ab * cb), axis=1)
 cros = np.cross(ab, cb)
 alpha = np.arctan2(cros, dot)
 return (alpha * (180.0 / np.pi))

def GetAnglesPolyline ( polyline , closed = False ) : points = polyline [ : , 0 ] if closed : a = np . roll ( points , 1 , axis = 0 ) b = points c = np . roll ( points , ( - 1 ) , axis = 0 ) else : a = points [ 0 : ( - 2 ) ] b = points [ 1 : ( - 1 ) ] c = points [ 2 : ] ab = ( b - a ) cb = ( b - c ) dot = np . sum ( ( ab * cb ) , axis = 1 ) cros = np . cross ( ab , cb ) alpha = np . arctan2 ( cros , dot ) return ( alpha * ( 180.0 / np . pi ) )
see: URL ported to numpy returns n-2 signed angles .