Coverage for src/min_circle/utils/circle.py: 100%
17 statements
« prev ^ index » next coverage.py v7.10.4, created at 2025-08-19 00:41 +0000
« prev ^ index » next coverage.py v7.10.4, created at 2025-08-19 00:41 +0000
1"""Circle utility class for representing and visualizing circles.
3This module provides a Circle class for representing circles in 2D space,
4with methods for checking point containment and visualization.
5"""
7from dataclasses import dataclass
9import numpy as np
10import plotly.graph_objects as go
13@dataclass(frozen=True)
14class Circle:
15 """A 2D circle representation.
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.
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 """
26 center: np.ndarray
27 radius: float
29 def __post_init__(self) -> None:
30 """Validate that the center is a 2D point.
32 Raises:
33 AssertionError: If the center is not a 2D point (shape != (2,))
34 """
35 assert self.center.shape == (2,), "Center must be a 2D point with shape (2,)"
37 def contains(self, point: np.ndarray, tolerance: float = 1e-10) -> bool:
38 """Check if a point lies within or on the circle.
40 Args:
41 point: A numpy array representing the point to check
42 tolerance: A small value to account for floating-point errors
44 Returns:
45 True if the point is inside or on the circle boundary, False otherwise
46 """
47 return np.linalg.norm(point - self.center) <= self.radius + tolerance
49 def scatter(self, num: int = 100, color: str = "red") -> go.Scatter:
50 """Create a Plotly Scatter trace representing the circle.
52 Args:
53 num: Number of points to use for drawing the circle
54 color: Color of the circle line
56 Returns:
57 A Plotly Scatter object that can be added to a figure
58 """
59 # Generate points along the circle
60 t = np.linspace(0, 2 * np.pi, num=num)
61 radius = self.radius
62 circle_x = self.center[0] + radius * np.cos(t)
63 circle_y = self.center[1] + radius * np.sin(t)
65 # Create and return the Scatter trace
66 return go.Scatter(
67 x=circle_x,
68 y=circle_y,
69 mode="lines",
70 line=dict(color=color, width=2),
71 name=f"Circle(r = {self.radius:.3f})",
72 )