Skip to content

Commit 266e54d

Browse files
icedcoffeeeepre-commit-ci[bot]Darylgolden
authoredJul 7, 2021
Added a static method to :class:~.Circle to allow it to be defined by three points (ManimCommunity#1765)
* Added new function: perpendicular bisector returns two points that form the perpendicular bisector of the points given * Circle mobject may accept three points. If the radius not specified, the three points may be given to form the circle. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update geometry.py * Added docs * perpendicular bisector can work in 3D * add test file * add test scene * Update manim/mobject/geometry.py Co-authored-by: Darylgolden <[email protected]> * changed the circle points test scene to addt * Added docs for perp bisector function space ops * typing error * Made a static method for a circle from three points * Added new test Co-authored-by: Iced-Tea3 <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Darylgolden <[email protected]>
1 parent c79034e commit 266e54d

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed
 

‎manim/mobject/geometry.py

+31
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def construct(self):
8787
compass_directions,
8888
line_intersection,
8989
normalize,
90+
perpendicular_bisector,
9091
regular_vertices,
9192
rotate_vector,
9293
)
@@ -583,6 +584,36 @@ def construct(self):
583584
start_angle = angle_of_vector(self.get_points()[0] - self.get_center())
584585
return self.point_from_proportion((angle - start_angle) / TAU)
585586

587+
@staticmethod
588+
def from_three_points(
589+
p1: Sequence[float], p2: Sequence[float], p3: Sequence[float], **kwargs
590+
):
591+
"""Returns a circle passing through the specified
592+
three points.
593+
594+
Example
595+
-------
596+
597+
.. manim:: CircleFromPointsExample
598+
:save_last_frame:
599+
600+
class CircleFromPointsExample(Scene):
601+
def construct(self):
602+
circle = Circle.from_three_points(LEFT, LEFT + UP, UP * 2, color=RED)
603+
dots = VGroup(
604+
Dot(LEFT),
605+
Dot(LEFT + UP),
606+
Dot(UP * 2),
607+
)
608+
self.add(NumberPlane(), circle, dots)
609+
"""
610+
center = line_intersection(
611+
perpendicular_bisector([p1, p2]),
612+
perpendicular_bisector([p2, p3]),
613+
)
614+
radius = np.linalg.norm(p1 - center)
615+
return Circle(radius=radius, **kwargs).shift(center)
616+
586617

587618
class Dot(Circle):
588619
"""A circle with a very small radius.

‎manim/utils/space_ops.py

+30
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"get_winding_number",
2828
"cross2d",
2929
"earclip_triangulation",
30+
"perpendicular_bisector",
3031
]
3132

3233

@@ -745,3 +746,32 @@ def earclip_triangulation(verts: np.ndarray, ring_ends: list) -> list:
745746

746747
meta_indices = earcut(verts[indices, :2], [len(indices)])
747748
return [indices[mi] for mi in meta_indices]
749+
750+
751+
def perpendicular_bisector(
752+
line: Sequence[np.ndarray], norm_vector=OUT
753+
) -> Sequence[np.ndarray]:
754+
"""Returns a list of two points that correspond
755+
to the ends of the perpendicular bisector of the
756+
two points given.
757+
758+
Parameters
759+
----------
760+
line
761+
a list of two numpy array points (corresponding
762+
to the ends of a line).
763+
norm_vector
764+
the vector perpendicular to both the line given
765+
and the perpendicular bisector.
766+
767+
Returns
768+
-------
769+
list
770+
A list of two numpy array points that correspond
771+
to the ends of the perpendicular bisector
772+
"""
773+
p1 = line[0]
774+
p2 = line[1]
775+
direction = np.cross(p1 - p2, norm_vector)
776+
m = midpoint(p1, p2)
777+
return [m + direction, m - direction]
Binary file not shown.

‎tests/test_graphical_units/test_geometry.py

+6
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ def construct(self):
4949
self.add(circle)
5050

5151

52+
class CirclePointsTest(Scene):
53+
def construct(self):
54+
circle = Circle.from_three_points(LEFT, LEFT + UP, UP * 2)
55+
self.add(circle)
56+
57+
5258
class DotTest(Scene):
5359
def construct(self):
5460
dot = Dot()

0 commit comments

Comments
 (0)
Please sign in to comment.