Skip to content


The Stripe Patterns on Surfaces algorithm efficiently computes evenly-spaced stripes on a surface, aligned with some direction field given as input. This section describes an implementation in geometry-central, along with functions to extract the isolines of the stripes as polyline curves along the surface. The original reference implementation of the Stripes algorithm can be found here.

Authors: Original algorithm by Felix Knöppel, Keenan Cranel, Ulrich Pinkall, Peter Schröder. Extraction & geometry-central integration by David Jourdan.

#include "geometrycentral/surface/stripe_patterns.h"

stripes isolines


// Generate a guiding field
VertexData<Vector2> guideField =
    geometrycentral::surface::computeSmoothestVertexDirectionField(*geometry, 2);

// Compute the stripe pattern
dougle constantFreq = 40.;
VertexData<double> frequencies(*mesh, constantFreq);
CornerData<double> periodicFunc;
FaceData<int> zeroIndices;
FaceData<int> branchIndices;
std::tie(periodicFunc, zeroIndices, branchIndices) =
    computeStripePattern(*geometry, frequencies, guideField);

// Extract isolines
std::vector<Vector3> isolineVerts;
std::vector<std::array<size_t, 2>> isolineEdges;
std::tie(isolineVerts, isolineEdges) = extractPolylinesFromStripePattern(
    *geometry, periodicFunc, zeroIndices, branchIndices, guideField, false);

Stripe Patterns

No surface interpolation

The Stripe Patterns paper describes a customized interpolation scheme to smoothly extend the scalar function on the interior of each triangle, even in the presence of singularities. That scheme is not yet implemented here; this implementation just computes a scalar function per-corner and extracts isolines. For the full scheme, see the original reference implementation.

std::tuple<CornerData<double>, FaceData<int>, FaceData<int>> computeStripePattern(IntrinsicGeometryInterface& geometry, const VertexData<double>& frequencies, const VertexData<Vector2>& directionField)

Compute a stripe pattern on the surface.

The direction field should be a 2-symmetric vector field, in the complex power representation.

std::tuple<std::vector<Vector3>, std::vector<std::array<size_t, 2>>> extractPolylinesFromStripePattern(EmbeddedGeometryInterface& geometry, const CornerData<double>& values, const FaceData<int>& stripeIndices, const FaceData<int>& fieldIndices, const VertexData<Vector2>& directionField, bool connectOnSingularities)

Process a stripe pattern ot extract isolines of the stripes as explicit polylines.

The direction field should be a 2-symmetric vector field, in the complex power representation.

Can optionally connect isolines separated by a singularity using a directionField alignment heuristic

std::tuple<std::vector<Vector3>, std::vector<std::array<size_t, 2>>> computeStripePatternPolylines(EmbeddedGeometryInterface& geometry, const VertexData<double>& frequencies, const VertexData<Vector2>& directionField, bool connectIsolinesOnSingularities = true)

Runs both of the above functions, computing the stripe pattern and extracting polylines from it.

The direction field should be a 2-symmetric vector field, in the complex power representation.


These algorithms are described in Stripe Patterns on Surfaces

   author = {Kn\"{o}ppel, Felix and Crane, Keenan and Pinkall, Ulrich and Schr\"{o}der, Peter},
   title = {Stripe Patterns on Surfaces},
   journal = {ACM Trans. Graph.},
   volume = {34},
   issue = {4},
   year = {2015},
   publisher = {ACM},
   address = {New York, NY, USA},