Coverage for src / min_circle / utils / circle.py: 100%

17 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-01-26 19:42 +0000

1"""Circle utility class for representing and visualizing circles. 

2 

3This module provides a Circle class for representing circles in 2D space, 

4with methods for checking point containment and visualization. 

5""" 

6 

7from dataclasses import dataclass 

8 

9import numpy as np 

10import plotly.graph_objects as go 

11 

12 

13@dataclass(frozen=True) 

14class Circle: 

15 """A 2D circle representation. 

16 

17 This class represents a circle in 2D space, defined by its center coordinates 

18 and radius. It provides methods for checking if points are contained within 

19 the circle and for visualizing the circle using Plotly. 

20 

21 Attributes: 

22 center: A numpy array of shape (2,) representing the x,y coordinates of the center 

23 radius: The radius of the circle 

24 

25 Examples: 

26 >>> import numpy as np 

27 >>> c = Circle(center=np.array([0.0, 0.0]), radius=1.0) 

28 >>> c.radius 

29 1.0 

30 >>> c.center 

31 array([0., 0.]) 

32 """ 

33 

34 center: np.ndarray 

35 radius: float 

36 

37 def __post_init__(self) -> None: 

38 """Validate that the center is a 2D point. 

39 

40 Raises: 

41 AssertionError: If the center is not a 2D point (shape != (2,)) 

42 """ 

43 assert self.center.shape == (2,), "Center must be a 2D point with shape (2,)" 

44 

45 def contains(self, point: np.ndarray, tolerance: float = 1e-10) -> bool: 

46 """Check if a point lies within or on the circle. 

47 

48 Args: 

49 point: A numpy array representing the point to check 

50 tolerance: A small value to account for floating-point errors 

51 

52 Returns: 

53 True if the point is inside or on the circle boundary, False otherwise 

54 

55 Examples: 

56 >>> import numpy as np 

57 >>> c = Circle(center=np.array([0.0, 0.0]), radius=1.0) 

58 >>> c.contains(np.array([0.0, 0.0])) # center point 

59 True 

60 >>> c.contains(np.array([1.0, 0.0])) # on boundary 

61 True 

62 >>> c.contains(np.array([0.5, 0.5])) # inside 

63 True 

64 >>> c.contains(np.array([1.0, 1.0])) # outside 

65 False 

66 """ 

67 return bool(np.linalg.norm(point - self.center) <= self.radius + tolerance) 

68 

69 def scatter(self, num: int = 100, color: str = "red") -> go.Scatter: 

70 """Create a Plotly Scatter trace representing the circle. 

71 

72 Args: 

73 num: Number of points to use for drawing the circle 

74 color: Color of the circle line 

75 

76 Returns: 

77 A Plotly Scatter object that can be added to a figure 

78 """ 

79 # Generate points along the circle 

80 t = np.linspace(0, 2 * np.pi, num=num) 

81 radius = self.radius 

82 circle_x = self.center[0] + radius * np.cos(t) 

83 circle_y = self.center[1] + radius * np.sin(t) 

84 

85 # Create and return the Scatter trace 

86 return go.Scatter( 

87 x=circle_x, 

88 y=circle_y, 

89 mode="lines", 

90 line={"color": color, "width": 2}, 

91 name=f"Circle(r = {self.radius:.3f})", 

92 )