Repository: ManimCommunity/manim
Pull request: Added new method :meth:`~.Mobject.get_midpoint`
<!--
Thanks for your contribution to ManimCommunity!

Before filling in the details, ensure:
- Your local changes are up-to-date with ManimCommunity/manim
  
- The title of your PR gives a descriptive summary to end-users. Some examples:
  - Fixed last animations not running to completion
  - Added gradient support and documentation for SVG files
  Examples of what *NOT* to do:
  - "fixed that styling issue" - not descriptive enough
  - "fixed issue #XYZ" - end-user needs to do further research
-->
## Changelog / Overview
There are already a lot of coordinates one can obtain from an mobject (https://docs.manim.community/en/stable/reference/manim.mobject.mobject.Mobject.html#manim.mobject.mobject.Mobject.get_bottom)
But it would be nice to also have the possibility to easily get the middle point of a line of an mobject with `get_midpoint`.
![image](https://user-images.githubusercontent.com/44469195/113411978-6eac0e80-93b7-11eb-8a6d-09c1b1e9eb6e.png)
This function is calling `self.point_from_proportion(0.5)`.
As `point_from_proportion` is implemented in `vmobject` and I implemented `get_midpoint` in `mobject`, is this something that would cause problems? And is this the pythonic way to do it?
## Changelog
<!--changelog-start--> 
Implemented :meth:`~.Mobject.get_midpoint` to return the point that is the middle of the stroke line of an mobject.
<!--changelog-end-->
## Checklist
- [x] I have read the [Contributing Guidelines](https://docs.manim.community/en/latest/contributing.html)
- [x] I have written a descriptive PR title (see top of PR template for examples)
- [x] I have written a changelog entry for the PR or deem it unnecessary
- [x] My new functions/classes either have a docstring or are private
- [ ] My new functions/classes have [tests](https://github.com/ManimCommunity/manim/wiki/Testing) added and (optional) examples in the docs
- [x] My new documentation builds, looks correctly formatted, and adds no additional build warnings
<!-- Once again, thanks for contributing to ManimCommunity! -->


<!-- Do not modify the lines below. These are for the reviewers of your PR -->
## Reviewer Checklist
- [ ] The PR title is descriptive enough
- [ ] The PR is labeled correctly
- [ ] The changelog entry is completed if necessary
- [ ] Newly added functions/classes either have a docstring or are private
- [ ] Newly added functions/classes have [tests](https://github.com/ManimCommunity/manim/wiki/Testing) added and (optional) examples in the docs
- [ ] Newly added documentation builds, looks correctly formatted, and adds no additional build warnings


Problem statement:
New idea for method: `get_middle_point`
Currently, there are a few methods to get positions like  `get_start`, `get_end` and `get_center` To get the middle of a line, it would be very convenient to have a method `get_middle_point` as well. It could look something like this:
```py
class Test(Scene):
    def construct(self):
        theta_tracker=ValueTracker(1)
        line1 = Line( LEFT, RIGHT)
        line2 = Line( LEFT, RIGHT ).rotate(theta_tracker.get_value()*DEGREES)

        a= Angle(line1, line2, radius=0.5, other_angle=False)
        def get_middle_point():
            po= a.get_points()
            return po[int(len(po)/2)]
        print(a.get_start())
        print(a.get_end())
        print(a.get_center())
        print(get_middle_point())
```
```console
[0.5 0.  0. ]
[0.49992385 0.0087262  0.        ]
[0.49996192 0.0043631  0.        ]
[0.49998096 0.00436327 0.        ]
```

Hints from issue discussion:
`mob.point_from_proportion(0.5)` could probably be used for this, right? Though for VMobject `point_from_proportion` works a little awkwardly because it doesn't take into account the length of each bezier curve..
I just added another print to my example and this works! 
```console
[0.5 0.  0. ]
[0.49992385 0.0087262  0.        ]
[0.49996192 0.0043631  0.        ]
[0.49998096 0.00436327 0.        ]
[0.49998096 0.00436327 0.        ] <-point_from_proportion
```
And yes, for bezier curves that might not work as expected.
And I just realized: For parametric functions, that would not work eighter because there is no equal spacing:
```py
class Test(Scene):
    def func(self, t):
        return np.array((np.cos(t), np.sin(t), 0))*(1-t*0.05)

    def construct(self):
        a = ParametricFunction(self.func, t_min=0, t_max = 2*TAU, fill_opacity=0).set_color(RED)
        self.add(a.scale(3))
        def get_middle_point():
            po= a.get_points()
            return po[int(len(po)/2)]
        print(a.get_start())
        print(a.get_end())
        print(a.get_center())
        print(get_middle_point())
        print(a.point_from_proportion(0.5))
        self.add(Dot(a.get_center()).set_color(GREEN))
        self.add(Dot(get_middle_point()).set_color(YELLOW).scale(3))
        self.add(Dot(a.point_from_proportion(0.5)).set_color(BLUE).scale(2))
        self.add(*[Dot(x) for x in a.get_points()[::200]])
```
![image](https://user-images.githubusercontent.com/44469195/113067500-bdda1f80-91bc-11eb-8d62-944832166af9.png)

So my idea right now:
adding the function
```py
def get_middle_point(self):
    return self.point_from_proportion(0.5)
```
to `mobject.py`
I think a better name would be `get_middle` to be in line with `get_start` etc.
I'm personally fond of `get_midpoint`.

Commit message: implemented get_midpoint

Patch to review:
diff --git a/manim/mobject/mobject.py b/manim/mobject/mobject.py
index e52aa9fb1c..bfe88a52cb 100644
--- a/manim/mobject/mobject.py
+++ b/manim/mobject/mobject.py
@@ -1724,6 +1724,29 @@ def get_boundary_point(self, direction):
         index = np.argmax(np.dot(all_points, np.array(direction).T))
         return all_points[index]
 
+    def get_midpoint(self) -> np.ndarray:
+        """Get coordinates of the middle of the line that forms the  :class:`~.Mobject`
+         Examples
+        --------
+
+        .. manim:: AngleMidPoint
+            :save_last_frame:
+
+            class AngleMidPoint(Scene):
+                def construct(self):
+                    line1 = Line(ORIGIN, 2*RIGHT)
+                    line2 = Line(ORIGIN, 2*RIGHT).rotate_about_origin(80*DEGREES)
+
+                    a = Angle(line1, line2, radius=1.5, other_angle=False)
+                    d=Dot(a.get_midpoint()).set_color(RED)
+
+                    self.add(line1, line2, a, d)
+                    self.wait()
+
+        """
+        return self.point_from_proportion(0.5)
+
+
     def get_top(self) -> np.ndarray:
         """Get top coordinates of a box bounding the :class:`~.Mobject`"""
         return self.get_edge_center(UP)


Code review comments:
diff_hunk: @@ -1724,6 +1724,29 @@ def get_boundary_point(self, direction):
         index = np.argmax(np.dot(all_points, np.array(direction).T))
         return all_points[index]
 
+    def get_midpoint(self) -> np.ndarray:
+        """Get coordinates of the middle of the line that forms the  :class:`~.Mobject`
+         Examples
path: manim/mobject/mobject.py
text: @author:
```suggestion
        Examples
```