Skip to content

Commit

Permalink
Merge b0ab364 into da34f33
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Mackey committed Aug 14, 2021
2 parents da34f33 + b0ab364 commit e013aab
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
15 changes: 15 additions & 0 deletions ladybug_geometry/geometry2d/pointvector.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,21 @@ def to_dict(self):
'x': self.x,
'y': self.y}

@staticmethod
def circular_mean(angles):
"""Compute the circular mean across a list of angles in radians.
If no circular mean exists, the normal mean will be returned.
Args:
angles: A list of angles in radians.
"""
avg_x = sum(math.cos(ang) for ang in angles) / len(angles)
avg_y = sum(math.sin(ang) for ang in angles) / len(angles)
if (avg_x, avg_y) == (0, 0): # just return the normal mean
return sum(angles) / len(angles)
return math.atan2(avg_y, avg_x)

def _cast_to_float(self, value):
"""Ensure that an input coordinate value is a float."""
try:
Expand Down
13 changes: 13 additions & 0 deletions tests/pointvector2d_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,16 @@ def test_reflect():
test_1 = pt_1.reflect(normal_2, origin_1)
assert test_1.x == pytest.approx(1, rel=1e-3)
assert test_1.y == pytest.approx(3, rel=1e-3)


def test_circular_mean():
"""Test the circular mean staticmethod."""
angles_1 = [math.radians(x) for x in [45, 315]]
angles_2 = [math.radians(x) for x in [45, 135]]
angles_3 = [math.radians(x) for x in [90, 270]]

assert Vector2D.circular_mean(angles_1) == pytest.approx(0, rel=1e-3)
assert Vector2D.circular_mean(angles_2) == \
pytest.approx(math.radians(90), rel=1e-3)
assert Vector2D.circular_mean(angles_3) == \
pytest.approx(math.radians(180), rel=1e-3)

0 comments on commit e013aab

Please sign in to comment.