Repository: ManimCommunity/manim
Pull request: Allow :class:`~.Cross` to be created without requiring a mobject
 <!--
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
<!-- Optional (Recommended): a detailed overview of the PR for the upcoming
release's changelog entry. Useful for when the PR title isn't enough. 

DO NOT REMOVE THE FOLLOWING CHANGELOG LINES, EVEN IF YOU DON'T USE THEM.-->
<!--changelog-start-->

<!--changelog-end-->

## Motivation
<!-- In what way do your changes improve the library? -->
The Cross class used to need Mobject instance to be initialized, however there was a need to create the Cross without a reference. 
Fixes #1838
## Explanation for Changes
<!-- How do your changes improve the library? -->
Cross can be added to the Scene independent of the Mobject upon which the Cross need to be fit.
_The following example has 'stroke_color=BLUE' set_

![Example3](https://user-images.githubusercontent.com/28934258/127776227-597f48ed-dc80-4672-9497-e543c4360f08.png)


Or if the Mobject is provided as arguments, it will fit to it.

![Example1](https://user-images.githubusercontent.com/28934258/127776252-b7dbad7c-1771-48bb-a3a4-be904eb8be5b.png)


If the scale_factor parameter is provided with or without the Mobject it will scale up to the specified value.

![Example2](https://user-images.githubusercontent.com/28934258/127776266-dcf62c0f-f48a-485a-8570-5aea2c0925fc.png)
```python
from manim import *


class ExampleCross(Scene):
    def construct(self):
        text = Text("Manim")
        cross = Cross(text, scale_factor=2)
        self.add(cross, text)
```


## Documentation Reference
<!-- Please include links to the affected documentation pages below. --> 


## Testing Status
<!-- Optional (Recommended): your computer specs and what tests you ran with
their results, if any. This section is also intended for other
testing-related comments. -->

## Further Comments
<!-- Optional: any further comments that might be useful for reviewers. -->

## 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
- [x] 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
- [x] The PR title is descriptive enough
- [x] The PR is labeled correctly
- [x] The changelog entry is completed if necessary
- [x] Newly added functions/classes either have a docstring or are private
- [x] Newly added functions/classes have [tests](https://github.com/ManimCommunity/manim/wiki/Testing) added and (optional) examples in the docs
- [x] Newly added documentation builds, looks correctly formatted, and adds no additional build warnings


Problem statement:
Allow `Cross` to be initialized without being based on an existing Mobject.
## Enhancement proposal
<!-- Add a clear and concise description of your enhancement proposal. In particular,
     if your enhancement introduces changes to the API, illustrate them with
     (fictional) code examples. -->

Currently Cross needs a mobject passed to it, I think it should be reworked to not necessarily require this. Also maybe easily specifying the length of the cross in the `__init__` too?


Current `Cross` code:
```py
class Cross(VGroup):
    def __init__(self, mobject, stroke_color=RED, stroke_width=6, **kwargs):
        VGroup.__init__(
            self,
            Line(UP + LEFT, DOWN + RIGHT),
            Line(UP + RIGHT, DOWN + LEFT),
        )
        self.replace(mobject, stretch=True)
        self.set_stroke(color=stroke_color, width=stroke_width)
```

## Additional comments
<!-- Add further context that you think might be relevant. -->
replacing `VGroup.__init__` with `super().__init__` too

Hints from issue discussion:
I could take this up, if its not an urgent fix.

PS: It would be my first contribution.
Sure, it's not urgent! I've assigned you to it👍

Commit message: Align Parameters doc text

Co-authored-by: Jan-Hendrik Müller <44469195+kolibril13@users.noreply.github.com>

Patch to review:
diff --git a/manim/mobject/shape_matchers.py b/manim/mobject/shape_matchers.py
index 4d4f39dde7..bdad8abc2d 100644
--- a/manim/mobject/shape_matchers.py
+++ b/manim/mobject/shape_matchers.py
@@ -2,10 +2,12 @@
 
 __all__ = ["SurroundingRectangle", "BackgroundRectangle", "Cross", "Underline"]
 
+from typing import Optional
 
 from ..constants import *
 from ..mobject.geometry import Line, Rectangle
-from ..mobject.types.vectorized_mobject import VGroup, VMobject
+from ..mobject.mobject import Mobject
+from ..mobject.types.vectorized_mobject import VGroup
 from ..utils.color import BLACK, RED, YELLOW, Color
 
 
@@ -117,13 +119,44 @@ def get_fill_color(self):
 
 
 class Cross(VGroup):
-    def __init__(self, mobject, stroke_color=RED, stroke_width=6, **kwargs):
-        VGroup.__init__(
-            self,
-            Line(UP + LEFT, DOWN + RIGHT),
-            Line(UP + RIGHT, DOWN + LEFT),
+    """Creates a cross.
+
+    Parameters
+    ----------
+    mobject
+        The mobject linked to this instance. It fits the mobject when specified. Defaults to None.
+    stroke_color
+        Specifies the color of the cross lines. Defaults to Red.
+    stroke_width
+        Specifies the width of the cross lines. Defaults to 6.
+    scale_factor
+        Scales the cross to the provided units. Defaults to 1.
+
+    Examples
+    --------
+    .. manim:: ExampleCross
+        :save_last_frame:
+
+        class ExampleCross(Scene):
+            def construct(self):
+                cross = Cross()
+                self.add(cross)
+    """
+
+    def __init__(
+        self,
+        mobject: Optional[Mobject] = None,
+        stroke_color: Optional[Color] = RED,
+        stroke_width: Optional[float] = 6,
+        scale_factor: Optional[float] = 1,
+        **kwargs
+    ):
+        super().__init__(
+            Line(UP + LEFT, DOWN + RIGHT), Line(UP + RIGHT, DOWN + LEFT), **kwargs
         )
-        self.replace(mobject, stretch=True)
+        if mobject is not None:
+            self.replace(mobject, stretch=True)
+        self.scale(scale_factor)
         self.set_stroke(color=stroke_color, width=stroke_width)
 
 


Code review comments:
diff_hunk: @@ -117,13 +119,44 @@ def get_fill_color(self):
 
 
 class Cross(VGroup):
-    def __init__(self, mobject, stroke_color=RED, stroke_width=6, **kwargs):
-        VGroup.__init__(
-            self,
-            Line(UP + LEFT, DOWN + RIGHT),
-            Line(UP + RIGHT, DOWN + LEFT),
+    """Creates a cross.
+
+    Parameters
+    ----------
+    mobject
+        The mobject linked to this instance. It fits the mobject when specified. Defaults to None.
+    stroke_color
+        Specifies the color of the cross lines. Defaults to Red.
+    stroke_width
+        Specifies the width of the cross lines. Defaults to 6.
+    scale_factor
+        Scales the cross to the provided units. Defaults to 1.
+
+    Examples
+    --------
+    .. manim:: ExampleCross
+        :save_last_frame:
+
+        class ExampleCross(Scene):
+            def construct(self):
+                cross = Cross()
+                self.add(cross)
+    """
+
+    def __init__(
+        self,
+        mobject: Optional[Mobject] = None,
+        stroke_color: Optional[Color] = RED,
+        stroke_width: Optional[float] = 6,
+        scale_factor: Optional[float] = 1,
path: manim/mobject/shape_matchers.py
text: @user1:
`Optional` is for when `None` is also a valid paramter, in these cases, it's not. So Optional is not appropriate here.
```suggestion
        stroke_color: Color = RED,
        stroke_width: float = 6,
        scale_factor: float = 1,
```

diff_hunk: @@ -117,13 +119,44 @@ def get_fill_color(self):
 
 
 class Cross(VGroup):
-    def __init__(self, mobject, stroke_color=RED, stroke_width=6, **kwargs):
-        VGroup.__init__(
-            self,
-            Line(UP + LEFT, DOWN + RIGHT),
-            Line(UP + RIGHT, DOWN + LEFT),
+    """Creates a cross.
+
+    Parameters
+    ----------
+    mobject
+        The mobject linked to this instance. It fits the mobject when specified. Defaults to None.
+    stroke_color
+        Specifies the color of the cross lines. Defaults to Red.
+    stroke_width
+        Specifies the width of the cross lines. Defaults to 6.
+    scale_factor
+        Scales the cross to the provided units. Defaults to 1.
+
+    Examples
+    --------
+    .. manim:: ExampleCross
+        :save_last_frame:
+
+        class ExampleCross(Scene):
+            def construct(self):
+                cross = Cross()
+                self.add(cross)
+    """
+
+    def __init__(
+        self,
+        mobject: Optional[Mobject] = None,
path: manim/mobject/shape_matchers.py
text: @user1:
Doesn't explicitly need to be a `Mobject`, so quotes are required here.
```suggestion
        mobject: Optional["Mobject"] = None,
```