Skip to content

Commit 0a09659

Browse files
committed
added attributes to Arc. created unittests
1 parent 1aab45f commit 0a09659

File tree

2 files changed

+142
-3
lines changed

2 files changed

+142
-3
lines changed

src/compas/geometry/primitives/arc.py

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import math
2+
3+
from compas.geometry import close
14
from compas.geometry.primitives import Frame
25
from compas.geometry.primitives import Primitive
36

@@ -12,8 +15,24 @@ class Arc(Primitive):
1215
radius : float
1316
Radius of the arc's circle.
1417
end_angle : float
15-
The angle in radians of the
16-
end_angle :
18+
The angle in radians of the end of this Arc.
19+
start_angle :
20+
The angle in radians of the start of this Arc.
21+
22+
Attributes
23+
----------
24+
length : float
25+
The length of the arc (radius * angle)
26+
angle : float
27+
The sweep angle in radians (between incrementing end angle and start angle).
28+
domain : tuple(float, float)
29+
A tuple containing the start and end angles of this arc, in radians.
30+
center : :class:`~compas.geometry.Point`
31+
The center point of the circle which coincides with this Arc.
32+
circumference : float
33+
The circumference of the circle which coincides with this Arc.
34+
diameter : float
35+
The diameter of the circle which coincides with this Arc.
1736
1837
"""
1938

@@ -22,9 +41,12 @@ def __init__(self, frame=None, radius=None, end_angle=None, start_angle=None, **
2241

2342
self._frame = frame
2443
self._radius = radius
25-
self._start_angle = start_angle
44+
self._start_angle = start_angle if start_angle is not None else 0.0
2645
self._end_angle = end_angle
2746

47+
if self._radius is not None and self._end_angle is not None:
48+
self._verify()
49+
2850
@property
2951
def data(self):
3052
return {"frame": self._frame.data, "radius": self._radius, "start": self._start_angle, "end": self._end_angle}
@@ -44,10 +66,65 @@ def frame(self):
4466
def radius(self):
4567
return self._radius
4668

69+
@property
70+
def length(self):
71+
return self.radius * self.angle
72+
4773
@property
4874
def start_angle(self):
4975
return self._start_angle
5076

5177
@property
5278
def end_angle(self):
5379
return self._end_angle
80+
81+
@property
82+
def angle(self):
83+
return self._end_angle - self._start_angle
84+
85+
@property
86+
def domain(self):
87+
return self._start_angle, self._end_angle
88+
89+
@property
90+
def center(self):
91+
return self.frame.point
92+
93+
@property
94+
def circumference(self):
95+
return 2.0 * math.pi * self.radius
96+
97+
@property
98+
def diameter(self):
99+
return 2.0 * self.radius
100+
101+
@property
102+
def is_circle(self):
103+
return close(abs(abs(self.angle) - 2.0 * math.pi), 0.0)
104+
105+
@classmethod
106+
def from_circle(cls, circle, start_angle, end_angle):
107+
"""Creates an Arc from a circle and start and end angles.
108+
109+
Parameters
110+
----------
111+
circle : :class:`~compas.geometry.Circle`
112+
The center point and radius of this circle will be used to create an Arc.
113+
start_angle : float
114+
The start angle in radians.
115+
end_angle : float
116+
The end angle in radians.
117+
118+
Returns
119+
-------
120+
:class:`~compas.geometry.Arc`
121+
122+
"""
123+
frame = Frame.worldXY()
124+
# TODO: take circle.frame once it has one
125+
frame.point = circle.center.copy()
126+
return cls(frame, circle.radius, end_angle, start_angle)
127+
128+
def _verify(self):
129+
if self.angle < 0.0 or self.angle > 2.0 * math.pi:
130+
raise ValueError("Sweep angle must satisfy 0 < angle < 2 * Pi. Currently:{}".format(self.angle))

tests/compas/geometry/test_arc.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import math
2+
import pytest
3+
4+
from compas.geometry import Arc
5+
from compas.geometry import Frame
6+
from compas.geometry import Plane
7+
from compas.geometry import Circle
8+
from compas.geometry import close
9+
10+
11+
@pytest.fixture
12+
def frame():
13+
return Frame([1.23, 0.44, -4.02], [1., 0., 0.], [0., 1., 0.])
14+
15+
16+
def test_create_arc(frame):
17+
arc = Arc(frame, 0.2, 1.14)
18+
19+
assert close(arc.angle, 1.14)
20+
assert close(arc.start_angle, 0.0)
21+
22+
23+
def test_create_arc_two_angles(frame):
24+
arc = Arc(frame,radius=8, start_angle=1.44, end_angle=3.14)
25+
26+
assert close(arc.radius, 8.0)
27+
assert close(arc.angle, 1.7)
28+
assert close(arc.start_angle, 1.44)
29+
assert close(arc.end_angle, 3.14)
30+
assert not arc.is_circle
31+
32+
33+
def test_create_from_circle(frame):
34+
circle = Circle(Plane(frame.point, frame.zaxis), 34.222)
35+
arc = Arc.from_circle(circle, 0.1, 0.443)
36+
37+
assert close(arc.radius, circle.radius)
38+
assert close(arc.angle, 0.343)
39+
assert close(arc.circumference, circle.circumference)
40+
assert close(arc.diameter, circle.diameter)
41+
assert arc.center == circle.center
42+
43+
44+
def test_create_from_circle_partial(frame):
45+
circle = Circle(Plane(frame.point, frame.zaxis), 34.222)
46+
arc = Arc.from_circle(circle, 0.1, 0.443)
47+
48+
assert not arc.is_circle
49+
50+
51+
def test_create_from_circle_full(frame):
52+
circle = Circle(Plane(frame.point, frame.zaxis), 34.222)
53+
arc = Arc.from_circle(circle, 0.0, 2.0 * math.pi)
54+
55+
assert close(arc.start_angle, 0.0)
56+
assert close(arc.angle, 2.0 * math.pi)
57+
assert arc.is_circle
58+
59+
60+
def test_create_invalid_arc(frame):
61+
with pytest.raises(ValueError):
62+
_ = Arc(frame, 0.2314, 7.14)

0 commit comments

Comments
 (0)