Skip to content

rmuzzar/repulsive-curves-python

Repository files navigation

Repulsive Curves - Python

A Python implementation of projected gradient-descent methods for repulsive optimization of polygonal curves, inspired by the paper Repulsive Curves by Yu, Schumacher, and Crane.

This project currently focuses on the (Sobolev preconditioned) $H¹$ projected gradient descent approach for evolving polygonal curves under repulsive energies. The long-term goal is to develop this into a full Python package for experimenting with repulsive curve energies, eventually including the (fractional Sobolev preconditioned) $H^s$ projected gradient descent approach from the paper.

There is an official C++ implementation associated with the original work at https://github.com/ythea/repulsive-curves.

The package provides three command-line apps:

repcurve-flow         Run projected gradient descent on an input OBJ curve.
repcurve-view         Open an interactive viewer for a saved gradient flow run.
repcurve-plot-energy  Plot energy histories from one or more saved runs.

Current status

This is the first working version of the Python package.

Planned future work includes:

  • a cleaner Python API,
  • better documentation for library usage,
  • a fractional $H^s$ Sobolev-gradient implementation,
  • more faithful comparisons with the methods in the Repulsive Curves paper,
  • more examples and tests.

Installation from scratch

These instructions assume you have no Python, no conda, and no Miniforge installed.

1. Install Miniforge

Do not install Python separately.

Install Miniforge first. Miniforge provides conda/mamba, which this project uses to create a reproducible environment.

On Windows:

  1. Go to the official Miniforge download page at https://github.com/conda-forge/miniforge/releases.
  2. Download the Windows x86_64 installer.
  3. Run the installer.
  4. Accept the default options unless you know you want something else.
  5. Open Miniforge Prompt.

Check that conda is available:

conda --version

Optionally check whether mamba is available:

mamba --version

It is okay if mamba is not found. The setup script will use mamba if available and fall back to conda otherwise.

2. Extract this project

Extract the project .zip.

The project folder should look roughly like this:

repulsive-curves-python/
├─ README.md
├─ LICENSE
├─ CITATION.cff
├─ pyproject.toml
├─ environment-base.yml
├─ environment-cpu.yml
├─ environment-cuda.yml
├─ scripts/
├─ src/
├─ inputs/
└─ outputs/

3. Open a terminal in the project folder

On Windows:

  1. Open Miniforge Prompt.
  2. In Miniforge Prompt, navigate to the project folder using the cd command.

After navigating to the project folder, check that you are in the correct folder:

dir

You should see files such as:

README.md
pyproject.toml

4. Run the setup script

Normal automatic install (inside Miniforge Prompt):

powershell -ExecutionPolicy Bypass -File scripts\setup_env.ps1

This will:

  1. Create a conda environment named repulsive-curves.
  2. Install the base scientific dependencies.
  3. Try to install CUDA PyTorch if a NVIDIA GPU is detected.
  4. Fall back to CPU PyTorch if CUDA does not work.
  5. Install this project in editable mode.
  6. Check that the command-line apps are available.

To force CPU-only installation:

powershell -ExecutionPolicy Bypass -File scripts\setup_env.ps1 -Cpu

To force a CUDA attempt:

powershell -ExecutionPolicy Bypass -File scripts\setup_env.ps1 -Cuda

The default automatic install is recommended for most users. Installation will likely take a while. Whenever prompted to Confirm changes: [Y/n] during install, enter Y.

5. Activate the environment

Each time you open a new Miniforge Prompt terminal and want to use the command-line apps directly, make sure to navigate to the project folder and activate the environment:

conda activate repulsive-curves

con Then the commands should be available:

repcurve-flow --help
repcurve-view --help
repcurve-plot-energy --help

If those commands print help messages, installation worked.

Basic workflow

The usual workflow is:

  1. Put an .obj curve file in inputs/.
  2. Run repcurve-flow to generate an .npz result file.
  3. Visualize the result with repcurve-view.
  4. Compare energy histories with repcurve-plot-energy.

Command-line apps

repcurve-flow

Main app. Runs projected gradient descent on an input polygonal curve, keeping edge lengths fixed throughout the flow (the curve barycenter also remains fixed).

Basic usage:

repcurve-flow inputs\knot.obj --preconditioner H1 --energy tpe --iters 2000 --verbose

This loads initial curve

inputs/knot.obj

, runs the flow starting at that curve, and saves an .npz file containing results in:

outputs/

repcurve-flow examples

Run projected gradient descent of the tangent-point energy on the input curve using an $H^1$ preconditioner:

repcurve-flow inputs\knot.obj --preconditioner H1 --energy tpe --iters 2000 --verbose

Run projected gradient descent of the Coulomb energy on the input curve using an $H^1$ preconditioner:

repcurve-flow inputs\knot.obj --preconditioner H1 --energy coulomb --iters 2000 --verbose

Run projected gradient descent of the tangent-point energy on the input curve using an $L^2$ preconditioner:

repcurve-flow inputs\knot.obj --preconditioner L2 --energy tpe --iters 2000 --verbose

Run projected gradient descent of the tangent-point energy on the input curve using no preconditioner:

repcurve-flow inputs\knot.obj --preconditioner none --energy tpe --iters 2000 --verbose

Run on CUDA, if CUDA PyTorch is installed and working:

repcurve-flow inputs\knot.obj --preconditioner H1 --energy tpe --device cuda --iters 2000 --verbose

Save each iterate as an .obj file:

repcurve-flow inputs\knot.obj --preconditioner H1 --energy tpe --iters 2000 --save-obj-frames

Important repcurve-flow options

--preconditioner H1      Use the H1 stiffness matrix preconditioner.
--preconditioner L2      Use the L2 mass matrix preconditioner.
--preconditioner none    Use the raw Euclidean gradient.

--energy tpe            Use tangent-point energy.
--energy coulomb        Use Coulomb-type energy.

--iters T               Maximum number of gradient flow iterations.
--device cpu            Use CPU PyTorch.
--device cuda           Use CUDA PyTorch.
--verbose               Print per-iterate information.
--save-obj-frames       Also save each iterate as an OBJ file.

For the full argument list, run command:

repcurve-flow --help

repcurve-view

Visualization app. Opens an interactive PyVista/Qt viewer for a saved .npz run.

Basic usage:

repcurve-view outputs\knot_tpe_H1.npz

The viewer allows you to:

  • scrub through the gradient flow iterates,
  • play/pause the evolution,
  • view projected-gradient arrows,
  • toggle lighting/visualization options,
  • export animation frames.

For help:

repcurve-view --help

repcurve-plot-energy

Energy plotting app. Plots energy histories from one or more saved .npz files.

Basic usage:

repcurve-plot-energy outputs\knot_tpe_H1.npz --labels "TPE H1"

Compare two runs:

repcurve-plot-energy outputs\knot_tpe_H1.npz outputs\knot_coulomb_H1.npz --labels "TPE H1" "Coulomb H1"

Compare $H^1$, $L^2$, and raw-gradient runs:

repcurve-plot-energy outputs\knot_tpe_H1.npz outputs\knot_tpe_L2.npz outputs\knot_tpe_none.npz --labels "H1" "L2" "raw"

For help:

repcurve-plot-energy --help

Input OBJ format

The input should be a polygonal curve stored in .obj format.

The file should contain:

v x y z

lines for vertices, and

l i j

lines for edges.

Example closed curve:

v 1 0 0
v 0 1 0
v -1 0 0
v 0 -1 0
l 1 2
l 2 3
l 3 4
l 4 1

Example open curve:

v 0 0 0
v 1 0 0
v 2 1 0
v 3 1 0
l 1 2
l 2 3
l 3 4

The curve should be a single polygonal chain (open or closed).

Output files

repcurve-flow saves .npz files in the outputs/ folder.

Each saved .npz file contains data such as (but not limited to):

traj            Curve vertices at each gradient flow iterate.
grads           Projected-gradient vectors (along the curve) at each iterate.
energies        Energy value at each iterate.
step_durations  Wall-clock timing data.
closed          Whether the input curve was closed.

These .npz files are used by:

repcurve-view
repcurve-plot-energy

Project structure

repulsive-curves-python/
│
├─ README.md
├─ pyproject.toml
├─ environment-base.yml
├─ environment-cpu.yml
├─ environment-cuda.yml
├─ .gitignore
│
├─ scripts/
│  ├─ setup_env.ps1
│  └─ setup_env.sh
│
├─ .vscode/
│  ├─ extensions.json
│  ├─ settings.json
│  ├─ tasks.json
│  └─ launch.json
│
├─ inputs/
│  └─ put input OBJ files here
│
├─ outputs/
│  └─ generated output files
│
└─ src/
   └─ repulsive_curves/
      ├─ __init__.py
      ├─ curve.py
      ├─ energies.py
      ├─ gradient_descent.py
      ├─ run_gradient_flow.py
      ├─ curve_evolution_visualization.py
      └─ plot_energy_histories.py

VS Code setup

After installation:

  1. Open the project folder in VS Code.
  2. Install the recommended extensions if prompted.
  3. Open a terminal in VS Code.
  4. Run:
conda activate repulsive-curves
  1. Press Ctrl+Shift+P.
  2. Search for Python: Select Interpreter.
  3. Select the environment named repulsive-curves.

License and citation

This project is released under the MIT License. See the LICENSE file for details.

This is an unofficial Python implementation/package inspired by the paper:

Christopher Yu, Henrik Schumacher, and Keenan Crane.
Repulsive Curves.
ACM Transactions on Graphics 40, no. 2, Article 10, 2021.
DOI: 10.1145/3439429.

The original paper and official C++ implementation are separate works by their respective authors. This project is not an official release of the original authors.

If you use this software in academic work, please cite both this software and the original paper.

This repository includes a CITATION.cff file so GitHub and citation tools can generate citation information automatically.

About

Python implementation of algorithms from the paper "Repulsive Curves" by Yu, Schumacher, and Crane.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors