# How to Use Manim's Coordinate Systems: A Complete Guide to Axes and ThreeDAxes

> Learn to use Manim's coordinate systems Axes and ThreeDAxes for 2D and 3D plotting. Explore coordinate conversion and graph plotting methods in this complete guide.

- Repository: [Grant Sanderson/manim](https://github.com/3b1b/manim)
- Tags: how-to-guide
- Published: 2026-02-28

---

**Manim's `CoordinateSystem` abstraction provides the `Axes` class for 2D plotting and `ThreeDAxes` for 3D surfaces, offering methods like `c2p()` for coordinate conversion and `get_graph()` for plotting curves and surfaces.**

Manim's animation engine relies heavily on Cartesian coordinate systems to position objects and plot mathematical functions. Whether you are creating 2D graphs or 3D surfaces, understanding the `CoordinateSystem` hierarchy in the `3b1b/manim` repository is essential for precise scene construction.

## Understanding the CoordinateSystem Abstraction

The foundation of all coordinate handling is the abstract class **`CoordinateSystem`**, defined in [`manimlib/mobject/coordinate_systems.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/coordinate_systems.py) (lines 54‑91). This class stores user‑supplied ranges and implements conversion helpers that subclasses inherit.

Key methods provided by the base class include:

- **`coords_to_point`** / **`point_to_coords`** – Map mathematical coordinates to scene points and vice‑versa (implemented by subclasses).
- **`get_axes`** / **`get_axis`** – Return the underlying `NumberLine` objects for each dimension.
- **`get_graph`** / **`get_parametric_curve`** – Build `ParametricCurve` objects that automatically respect the coordinate system's scaling.
- **Helper utilities** – `get_v_line`, `get_h_line`, `get_axis_label` for quickly drawing perpendiculars and labels.

## Working with 2D Axes

### Instantiating Axes and Configuring Ranges

The **`Axes`** class is a concrete subclass of `CoordinateSystem` that creates two orthogonal `NumberLine`s (X and Y) bundled in a `VGroup`. Its constructor resides in [`manimlib/mobject/coordinate_systems.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/coordinate_systems.py) (lines 46‑90).

Range specification uses `x_range` and `y_range` parameters, which accept either a 2‑tuple `(min, max)` or a 3‑tuple `(min, max, step)`. Internally, these are normalized by `full_range_specifier` (lines 48‑52). Each axis is built via `create_axis`, which instantiates a `NumberLine` (see [`manimlib/mobject/number_line.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/number_line.py), lines 27‑35) and recenters it at the origin.

### Coordinate Conversion with c2p and p2c

To place objects at specific mathematical coordinates, use the **`c2p`** (coords to point) and **`p2c`** (point to coords) shorthand methods. These wrap `coords_to_point` and `point_to_coords`, adding the vectors from the origin to each axis' number point.

```python
pt = axes.c2p(3, -2)          # Returns a 3-D scene point at x=3, y=-2

x, y = axes.p2c(pt)           # Returns (3.0, -2.0)

```

### Plotting Functions and Curves

The **`get_graph`** method constructs a `ParametricCurve` from a lambda or function. It automatically handles scaling according to the axis ranges.

```python
from manim import *

class TwoDAxesExample(Scene):
    def construct(self):
        # Create axes ranging from -8 to 8 on x and -4 to 4 on y

        axes = Axes(
            x_range=(-8, 8, 1),
            y_range=(-4, 4, 1),
            axis_config={"color": BLUE},
        )
        axes.add_axis_labels()        # adds "x" and "y"

        axes.add_coordinate_labels()  # numbers the ticks

        # Plot y = sin(x)

        sine = axes.get_graph(lambda x: np.sin(x), color=RED)

        # Label the curve

        label = axes.get_graph_label(sine, label="\\sin(x)")

        self.play(Create(axes), Create(sine), Write(label))
        self.wait()

```

Key implementation details referenced in this example include the `Axes` constructor (lines 46‑90), `axes.get_graph` (lines 84‑92), and `axes.get_graph_label` (lines 84‑92) in [`coordinate_systems.py`](https://github.com/3b1b/manim/blob/main/coordinate_systems.py).

## Extending to 3D with ThreeDAxes

### Setting Up Three-Dimensional Axes

**`ThreeDAxes`** inherits from `Axes` and adds a third orthogonal Z‑axis. Its implementation occupies lines 35‑74 in [`manimlib/mobject/coordinate_systems.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/coordinate_systems.py).

The Z‑axis is created using the same `create_axis` helper, then rotated `-π/2` around the UP direction and oriented to a user‑specified normal (`z_normal`, defaulting to `DOWN`) (lines 62‑66). All three axes are stored in `self.axes` and added as a separate mobject so they behave like a standard `VGroup`.

### Plotting 3D Surfaces and Vectors

For 3D plotting, **`get_graph`** (lines 85‑106) builds a `ParametricSurface` from a function `f(u, v)`. It automatically scales function values by the unit size of each axis and translates them to the origin, allowing you to write `axes.get_graph(lambda u, v: u**2 - v**2)` without manual scaling.

```python
from manim import *

class ThreeDAxesExample(ThreeDScene):
    def construct(self):
        # Three‑dimensional axes

        three_axes = ThreeDAxes(
            x_range=(-6, 6, 1),
            y_range=(-5, 5, 1),
            z_range=(-4, 4, 1),
        )
        three_axes.add_axis_labels()   # "x", "y", "z"

        # Define surface z = x**2 - y**2

        surface = three_axes.get_graph(
            lambda u, v: u**2 - v**2,
            color=GREEN,
            opacity=0.6,
        )
        # Add a vector from the origin to a point on the surface

        vector = three_axes.get_vector([2, 1, 3], color=YELLOW)

        self.set_camera_orientation(phi=75 * DEGREES, theta=-45 * DEGREES)
        self.add(three_axes, surface, vector)
        self.wait()

```

Key implementation references include `ThreeDAxes` constructor (lines 35‑74), `three_axes.get_graph` (lines 85‑106), and `three_axes.get_vector` (line 179‑181).

## Common Workflows and Utilities

Beyond basic plotting, Manim coordinate systems provide utilities for annotation and measurement:

1. **Auxiliary geometry** – Draw vertical or horizontal reference lines with `axes.get_v_line(point)` or `axes.get_h_line(point)`.
2. **Axis labeling** – Use `add_axis_labels()` for quick "x", "y", "z" labels, or `get_axis_label()` for custom text.
3. **Riemann sums and tangents** – Helper methods exist for drawing rectangles under curves and tangent lines, all operating relative to the coordinate system origin and scaling.
4. **Exact placement** – Always use `c2p(x, y)` or `c2p(x, y, z)` to ensure objects align with mathematical coordinates rather than raw scene coordinates.

## Key Source Files

| File | Role |
|------|------|
| [`manimlib/mobject/coordinate_systems.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/coordinate_systems.py) | Core `CoordinateSystem`, `Axes`, `ThreeDAxes` definitions and utility methods. |
| [`manimlib/mobject/number_line.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/number_line.py) | Implements the `NumberLine` used by `Axes` for tick marks, numbering and conversion helpers (`n2p`, `p2n`). |
| [`manimlib/constants.py`](https://github.com/3b1b/manim/blob/main/manimlib/constants.py) | Provides direction vectors (`UP`, `DOWN`, `RIGHT`, …) and other constants referenced throughout the coordinate system code. |
| [`manimlib/mobject/types/vectorized_mobject.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/types/vectorized_mobject.py) | Supplies `VGroup` and `VMobject` base classes which `Axes` and `ThreeDAxes` extend. |
| [`manimlib/mobject/functions.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/functions.py) | Contains `ParametricCurve` used by `CoordinateSystem.get_graph`. |
| [`manimlib/mobject/types/surface.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/types/surface.py) | Supplies `ParametricSurface` used by `ThreeDAxes.get_graph`. |

## Summary

- **`CoordinateSystem`** is the abstract base in [`manimlib/mobject/coordinate_systems.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/coordinate_systems.py) that defines ranges and the API for plotting.
- **`Axes`** creates 2D Cartesian systems using `NumberLine` objects, supporting `x_range`/`y_range` tuples and coordinate conversion via `c2p()` and `p2c()`.
- **`ThreeDAxes`** extends `Axes` with a Z‑axis (rotated and oriented via `z_normal`) and provides `get_graph()` for `ParametricSurface` plotting.
- Use **`get_graph`**, **`get_parametric_curve`**, and **`get_vector`** to plot mathematical objects that automatically respect axis scaling.
- Reference **[`manimlib/mobject/number_line.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/number_line.py)** for tick mark logic and **[`manimlib/mobject/types/surface.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/types/surface.py)** for 3D surface rendering.

## Frequently Asked Questions

### How do I convert mathematical coordinates to scene points in Manim?

Use the **`c2p()`** method (short for `coords_to_point`). For a 2D system, call `axes.c2p(x, y)`; for 3D, use `three_axes.c2p(x, y, z)`. This returns a point in scene coordinates that respects the axis ranges and scaling defined in `x_range`, `y_range`, or `z_range`. To reverse the conversion, use **`p2c()`** (`point_to_coords`).

### What is the difference between Axes and ThreeDAxes in Manim?

**`Axes`** is a 2D Cartesian system inheriting from `CoordinateSystem`, creating X and Y `NumberLine`s. **`ThreeDAxes`** inherits from `Axes` and adds a third Z‑axis, which is created via `create_axis`, rotated `-π/2` around the UP vector, and oriented to a `z_normal` (default `DOWN`). `ThreeDAxes` also overrides `get_graph()` to return `ParametricSurface` objects for 3D plotting.

### How do I plot a 3D surface using ThreeDAxes?

Call **`three_axes.get_graph(func)`** where `func` is a lambda taking two arguments (typically `u` and `v`). For example, `three_axes.get_graph(lambda u, v: u**2 - v**2)` plots a hyperbolic paraboloid. The method (lines 85‑106 in [`coordinate_systems.py`](https://github.com/3b1b/manim/blob/main/coordinate_systems.py)) automatically scales the output by the unit size of each axis and translates it to the origin, returning a `ParametricSurface` instance.

### Where are the coordinate system classes defined in the Manim source code?

The core definitions reside in **[`manimlib/mobject/coordinate_systems.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/coordinate_systems.py)**. The abstract `CoordinateSystem` class is defined at lines 54‑91, the concrete `Axes` class at lines 46‑90, and `ThreeDAxes` at lines 35‑74. The underlying `NumberLine` implementation used by these axes is found in **[`manimlib/mobject/number_line.py`](https://github.com/3b1b/manim/blob/main/manimlib/mobject/number_line.py)**.