Skip to main content

Manim Vision: spatial collision intelligence for Manim scenes.

Project description

Manim Vision

Manim Vision adds production-oriented 2D spatial collision awareness to Manim Community scenes. It tracks VMobject geometry in the background, detects overlaps with Shapely and a STRtree broad phase, and emits JSON “spatial health” reports (with suggested shift(...) fix strings) to help you find unintentional object overlap while you build animations.

PyPI pip install manim-vision
Python 3.10, 3.11, or 3.12
License MIT

Table of contents


What it does

  • Hooks your live Scene so add, play, and remove participate in a collision pipeline (via a dynamically merged mixin; your scene class is unchanged at import time).
  • Wraps added VMobjects with a transparent proxy that refreshes stored geometry when you call common spatial methods (shift, scale, rotate, move_to, next_to, align_to, set_x / set_y / set_z, stretch, apply_matrix, apply_function).
  • Detects pairwise overlaps using Shapely (narrow phase, with DE-9IM / intersection area) on top of a Shapely STRtree for broad phase.
  • Relaxes overlapping pairs with an internal force-based iteration and computes MTV-style separation hints (ConstraintSolver).
  • Emits one validated JSON document per collision to stdout by default (JSON Schema: MANIM_VISION_SPATIAL_REPORT_SCHEMA in manim_vision.telemetry.schema).

Collision work runs on a dedicated single-worker thread pool so the main animation thread is not blocked by geometry queries.


Installation

pip install manim-vision

Dependencies are declared in pyproject.toml and include at least: manim, shapely, wrapt, numpy, and jsonschema.


Quick start

Call ManimVision.monitor(self) early in construct() (after you have a real Scene instance). Use your scene as usual: add, play, and remove are instrumented automatically.

from manim import BLUE, RED, Create, Circle, Scene, Square
from manim_vision import ManimVision


class MyScene(Scene):
    def construct(self):
        ManimVision.monitor(self)

        a = Circle(radius=1, color=BLUE)
        b = Square(side_length=1.2, color=RED)
        b.next_to(a, RIGHT, buff=0)  # may overlap — reported if so

        self.add(a, b)
        self.play(Create(a), Create(b))

        ManimVision.shutdown(self)  # recommended: see below

Lazy import: manim_vision loads lightweight symbols (ManimVisionError, etc.) immediately; ManimVision is loaded from manim_vision.core the first time you access it, so imports stay cheap when Manim is not yet needed.


Shutting down cleanly

ManimVision.shutdown(self) (or the mixin’s shutdown() on the scene) waits for queued collision jobs and shuts down the worker thread pool before the scene / process tears down. Use it at the end of construct() or after your last add / play in long or scripted runs to avoid pending work or pool warnings at exit.


How it works (architecture)

  1. ManimVision.monitor(scene) checks that scene is a Manim Scene, then attaches an engine, solver, telemetry dispatcher, registry lock, and executor to the instance. It rebases scene.__class__ to a new type that prepends ManimVisionSceneMixin in the MRO so add / play / remove are overridden while the rest of your class behaves as before.
  2. add wraps each VMobject in a ManimVisionMobjectProxy, which registers it with PrecisionGeometryEngine and updates geometry after spatial mutators.
  3. After add and play, a collision check is submitted to the executor. Under the scene lock, the engine checks collisions, the solver applies relaxation and MTV math, and the TelemetryDispatcher writes JSON to the configured stream (default stdout).
  4. remove deregisters mobjects from the engine’s registry.

Internal pieces (for reading the code or building on top of the library):

Component Role
GeometryAdapter Converts VMobject outlines to Shapely geometry (with validation / error handling).
PrecisionGeometryEngine Registry, STRtree queries, CollisionResult build-out.
ConstraintSolver MTV / SAT-style hints, force relaxation, shift(...) fix string generation.
TelemetryDispatcher Builds payloads, validates against JSON Schema, writes JSON lines.

Telemetry output

Each report is a single JSON object (pretty-printed with indentation in the default dispatcher) with fields such as:

  • timestamp — ISO-8601 UTC
  • scene_name — Sanitized scene class name
  • error_type — e.g. OVERLAP (see schema for allowed values)
  • colliding_entities — String labels ClassName_id for the two mobjects
  • overlap_area — Positive float in world units²
  • resolution_mtvx, y, z components (2D analysis uses z: 0)
  • fix_suggestion — Suggested Manim code, often chained shift(UP * …).shift(RIGHT * …) style

The contract is defined in code as MANIM_VISION_SPATIAL_REPORT_SCHEMA in manim_vision/telemetry/schema.py. Invalid payloads raise ManimVisionSchemaError.

To capture telemetry to a file when driving Manim headlessly, redirect stdout or construct a TelemetryDispatcher(output_stream=...) in advanced integrations (the default path used by the stock pipeline points at sys.stdout).


Public API and exceptions

Entry points

  • manim_vision.ManimVisionmonitor(scene), shutdown(scene).

Exceptions (re-exported from manim_vision)

Exception Meaning
ManimVisionError Base error (e.g. monitor() given a non-Scene).
ManimVisionGeometryError VMobject could not be turned into valid geometry.
ManimVisionSchemaError Telemetry payload failed JSON Schema validation.
ManimVisionProxyError Reserved for proxy/instrumentation failures.

Lower-level types (used in tests and extensions) live under manim_vision.geometry, manim_vision.proxy, manim_vision.solver, and manim_vision.telemetry — e.g. ManimVisionSceneProxy, PrecisionGeometryEngine, CollisionResult, ConstraintSolver, TelemetryDispatcher.


Design notes and limitations

  • 2D-style analysis in the engine: separation vectors use xy; mobjects are approximated for outline overlap in the scene plane. Not a full 3D physics engine.
  • VMobject-oriented: tracking is built around vectorized mobjects; exotic object types may not register or may log conversion warnings.
  • Touches vs overlap: pairs that only touch (zero area) are filtered out; positive overlap area is what triggers a report.
  • Heavier geometry (e.g. concave shapes) may use centroid / convex-hull fallbacks in the solver; see ConstraintSolver docstrings and implementation for details.
  • The library aims to be non-invasive: it does not replace your self reference; it only replaces the runtime class of the scene object to install hooks.

Development

From a checkout of the package root (the directory that contains pyproject.toml):

python -m venv .venv
.venv\Scripts\activate          # Windows
# source .venv/bin/activate     # macOS / Linux

pip install -e ".[dev]"
python -m pytest

Run Ruff or your usual formatter if you keep them in the project; tests use pytest with asyncio mode as configured in pyproject.toml.


License

MIT — see the LICENSE file in this repository.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

manim_vision-0.1.1.tar.gz (21.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

manim_vision-0.1.1-py3-none-any.whl (23.4 kB view details)

Uploaded Python 3

File details

Details for the file manim_vision-0.1.1.tar.gz.

File metadata

  • Download URL: manim_vision-0.1.1.tar.gz
  • Upload date:
  • Size: 21.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0

File hashes

Hashes for manim_vision-0.1.1.tar.gz
Algorithm Hash digest
SHA256 494d57fffbbda9b226b4ca2cee50eaaf4334ee1b2f433d1687a663fbc3b4b944
MD5 bebd3cce20aa79ab4cc4eaccf02ed073
BLAKE2b-256 15be040cd4df8f5241fc06be1166398ad01c43635e6b4d9d91a53c9f5613d8b9

See more details on using hashes here.

File details

Details for the file manim_vision-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: manim_vision-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 23.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0

File hashes

Hashes for manim_vision-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c1e180335604f1da81360f45afea75e51daa140232dd0db4db416b7700e6bd48
MD5 c276181fd238ec13f332b4d841353afe
BLAKE2b-256 25e0d978bd38aec125795eb26e87c503fed6cda54d7057beba86be081f867f29

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page