Skip to content

Conversation

henrikmidtiby
Copy link
Contributor

This is a fix for issue #4182

Overview: What does this pull request change?

In some cases the stroke_width parameter is not saved as a np.ndarray but a float or int instead.
In that case the len(...) call will fail in the align_data method in opengl_mobject.py.

In the PR the for loop in align_data is also skipped for data with the key stroke_width or if the self.data[key] is of type int in the interpolate method.

Reviewer Checklist

  • The PR title is descriptive enough for the changelog, and the PR is labeled correctly
  • If applicable: newly added non-private functions and classes have a docstring including a short summary and a PARAMETERS section
  • If applicable: newly added functions and classes are tested

@github-project-automation github-project-automation bot moved this to 🆕 New in Dev Board Aug 4, 2025
@henrikmidtiby henrikmidtiby marked this pull request as ready for review August 6, 2025 20:10
@behackl
Copy link
Member

behackl commented Aug 7, 2025

Wouldn't it be better to make sure the stroke_width is actually stored as a numpy array? (I don't have a strong opinion on this though, I'd also be willing to merge this as-is.)

Thanks for your effort!

@henrikmidtiby
Copy link
Contributor Author

Wouldn't it be better to make sure the stroke_width is actually stored as a numpy array?
I think it would be a cleaner solution to make it a numpy array.

In this branch https://github.com/henrikmidtiby/manim/commits/Issue4182MakeArray/ I have tried to make stroke_width an np.array in all locations in opengl_vectorized_mobject.py.
In that case it works fine with all the unit tests, but the example given in issue #4182 (comment) would now fail with the error shown below.

│ /home/hemi/localbuild/manim/manim/renderer/opengl_renderer.py:340 in render_mobject              │
│                                                                                                  │
│   337 │   │   │   if config["use_projection_stroke_shaders"]:                                    │
│   338 │   │   │   │   render_opengl_vectorized_mobject_stroke(self, mobject)                     │
│   339 │   │                                                                                      │
│ ❱ 340 │   │   shader_wrapper_list = mobject.get_shader_wrapper_list()                            │
│   341 │   │                                                                                      │
│   342 │   │   # Convert ShaderWrappers to Meshes.                                                │
│   343 │   │   for shader_wrapper in shader_wrapper_list:                                         │
│                                                                                                  │
│ /home/hemi/localbuild/manim/manim/mobject/opengl/opengl_vectorized_mobject.py:1548 in            │
│ get_shader_wrapper_list                                                                          │
│                                                                                                  │
│   1545 │   │   for submob in self.family_members_with_points():                                  │
│   1546 │   │   │   if submob.has_fill() and not config["use_projection_fill_shaders"]:           │
│   1547 │   │   │   │   fill_shader_wrappers.append(submob.get_fill_shader_wrapper())             │
│ ❱ 1548 │   │   │   if submob.has_stroke() and not config["use_projection_stroke_shaders"]:       │
│   1549 │   │   │   │   ssw = submob.get_stroke_shader_wrapper()                                  │
│   1550 │   │   │   │   if submob.draw_stroke_behind_fill:                                        │
│   1551 │   │   │   │   │   back_stroke_shader_wrappers.append(ssw)                               │
│                                                                                                  │
│ /home/hemi/localbuild/manim/manim/mobject/opengl/opengl_vectorized_mobject.py:455 in has_stroke  │
│                                                                                                  │
│    452 │   │   return (                                                                          │
│    453 │   │   │   stroke_widths is not None                                                     │
│    454 │   │   │   and stroke_opacities is not None                                              │
│ ❱  455 │   │   │   and any(stroke_widths)                                                        │
│    456 │   │   │   and any(stroke_opacities)                                                     │
│    457 │   │   )                                                                                 │
│    458                                                                                           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: iteration over a 0-d array

This seems to be caused by the SVGMobject, which sets the stroke_width property to a float an I cannot locate where.

if self.stroke_width is None:
self.stroke_width = 0
if stroke_width is None:
self.stroke_width = None

Check warning

Code scanning / CodeQL

Overwriting attribute in super-class or sub-class Warning

Assignment overwrites attribute stroke_width, which was previously defined in superclass
VMobject
.
if stroke_width is None:
self.stroke_width = None
else:
self.stroke_width = np.array([[stroke_width]]) # type: ignore[assignment]

Check warning

Code scanning / CodeQL

Overwriting attribute in super-class or sub-class Warning

Assignment overwrites attribute stroke_width, which was previously defined in superclass
VMobject
.
@henrikmidtiby henrikmidtiby marked this pull request as draft August 25, 2025 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🆕 New
Development

Successfully merging this pull request may close these issues.

2 participants