min ½‖δ‖² + λ/2‖∇(w + δ)‖²
s.t. C(w + δ)=0, ‖wᵢ‖=1This curved-surface stage chooses the foliation direction. The flat browser demo starts from a supplied field so the second optimization stays legible.
A real potential is awkward across periods and branch points. Instead, store a complex phase ψᵢ at each vertex, convert the target vector field into an edge phase increment ωᵢⱼ, and minimize the mismatch after phase transport.
minψ Σij wij |ψj − exp(iωij)ψi|²
subject to ‖ψ‖²M = 1
min ½‖δ‖² + λ/2‖∇(w + δ)‖²
s.t. C(w + δ)=0, ‖wᵢ‖=1This curved-surface stage chooses the foliation direction. The flat browser demo starts from a supplied field so the second optimization stays legible.
∇θ ≈ s w⊥ or (d − iω)ψ ≈ 0The live solve below uses the sparse connection energy. Global normalization avoids the zero solution; local amplitude can fall near incompatible regions and signal stripe singularities.
How to read it
Arrows are the requested phase-gradient direction. Stripes should run orthogonal to them.
Color is a periodic function of arg ψ. No global cut or unwrapped real coordinate is needed.
Brightness is |ψ|. Dark points are where rescaling makes room for incompatibility or a branch point.
Local curl, global periods, periodic phase, and amplitude zeros are different modeling choices. This energy measures edge-wise phase transport and solves a globally normalized sparse eigenproblem; the earlier triangle-circulation penalty acts directly on vertex vectors.
An explicit rescaling field s can first be optimized so s w⊥ + δ lies near the integrable subspace, then alternated with the periodic phase solve. Keeping these two optimizations visible is useful when moving to geodesic foliations.
This teaching canvas samples phase on the displayed grid, so coarse/high-frequency combinations alias. The original Stripe Patterns method also develops a nonlinear interpolant for rendering above mesh resolution.
The solver is deliberately small: a sparse connection-Laplacian matvec, gradient step, and mass normalization. The research version replaces this iteration with a sparse generalized eigensolver and adds the explicit s/θ alternation.
Face frames instead of vertex vectors
A 4-RoSy frame is encoded by two tangent vectors α and β. Polynomial coefficients stay unchanged when those directions are permuted or sign-flipped; shared-edge residuals can therefore compare frames more symmetrically.
C₀ = α²β² C₂ = −(α² + β²)
This compact explorer shows the smooth coefficient mismatch and the edge-projected PolyCurl mismatch. Purple and cyan arrows are the two one-sided frame vectors; their dashed drops and thick arrows show each scalar projection onto the common edge before coefficient reduction. The full TinyAD example adds quotient and barrier residuals and optimizes four variables per face.
Read the complete TinyAD PolyCurl example ↗