Skip to content

Smooth Curves and Curve Interpolation ​

Observable Plot supports various curve interpolation methods for line and area marks. This guide demonstrates all available curve types and when to use each one.

Linear Curves (Default) ​

Straight Line Segments ​

The default curve connects points with straight lines:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 20},
      {"x": 1, "y": 35},
      {"x": 2, "y": 25},
      {"x": 3, "y": 45},
      {"x": 4, "y": 30},
      {"x": 5, "y": 50}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: linear
      stroke: steelblue
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 4
      fill: steelblue

When to Use:

  • Default behavior (no curve specified)
  • Sharp transitions are meaningful
  • Minimal smoothing desired
  • Performance-critical applications

Step Curves ​

Step After ​

Creates horizontal then vertical segments (step-after):

data-glass
data:
  source: |
    [
      {"time": 0, "value": 10},
      {"time": 1, "value": 25},
      {"time": 2, "value": 20},
      {"time": 3, "value": 40},
      {"time": 4, "value": 35}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: time
      y: value
      curve: step-after
      stroke: darkorange
      strokeWidth: 2
  - type: dot
    configuration:
      x: time
      y: value
      r: 3
      fill: darkorange

Use Cases:

  • Digital signals
  • State changes
  • Inventory levels
  • Constant value between observations

Step Before ​

Creates vertical then horizontal segments (step-before):

data-glass
data:
  source: |
    [
      {"time": 0, "value": 10},
      {"time": 1, "value": 25},
      {"time": 2, "value": 20},
      {"time": 3, "value": 40},
      {"time": 4, "value": 35}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: time
      y: value
      curve: step-before
      stroke: purple
      strokeWidth: 2
  - type: dot
    configuration:
      x: time
      y: value
      r: 3
      fill: purple

Use Cases:

  • Leading indicators
  • Future projections
  • Forward-looking data

Step (Middle) ​

Creates steps centered on data points:

data-glass
data:
  source: |
    [
      {"time": 0, "value": 10},
      {"time": 1, "value": 25},
      {"time": 2, "value": 20},
      {"time": 3, "value": 40},
      {"time": 4, "value": 35}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: time
      y: value
      curve: step
      stroke: green
      strokeWidth: 2
  - type: dot
    configuration:
      x: time
      y: value
      r: 3
      fill: green

Use Cases:

  • Centered step functions
  • Histogram-like line charts
  • Categorical transitions

Smooth Curves ​

Basis Spline ​

Creates smooth B-spline curves:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 20},
      {"x": 1, "y": 35},
      {"x": 2, "y": 25},
      {"x": 3, "y": 45},
      {"x": 4, "y": 30},
      {"x": 5, "y": 50}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: basis
      stroke: "#e74c3c"
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 3
      fill: "#e74c3c"

Characteristics:

  • Very smooth curves
  • May not pass through control points
  • Good for general smoothing
  • Creates aesthetically pleasing curves

Cardinal Spline ​

Creates interpolated curves with adjustable tension:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 20},
      {"x": 1, "y": 35},
      {"x": 2, "y": 25},
      {"x": 3, "y": 45},
      {"x": 4, "y": 30},
      {"x": 5, "y": 50}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: cardinal
      stroke: "#9b59b6"
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 3
      fill: "#9b59b6"

Characteristics:

  • Passes through all data points
  • Smooth interpolation
  • Adjustable tension parameter
  • Good balance of smoothness and accuracy

Catmull-Rom Spline ​

Creates smooth curves passing through all points:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 20},
      {"x": 1, "y": 35},
      {"x": 2, "y": 25},
      {"x": 3, "y": 45},
      {"x": 4, "y": 30},
      {"x": 5, "y": 50}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: catmull-rom
      stroke: "#3498db"
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 3
      fill: "#3498db"

Characteristics:

  • Passes through all control points
  • Very smooth appearance
  • Popular for general smoothing
  • Good for presentation graphics

Natural Spline ​

Creates smooth curves with natural boundary conditions:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 20},
      {"x": 1, "y": 35},
      {"x": 2, "y": 25},
      {"x": 3, "y": 45},
      {"x": 4, "y": 30},
      {"x": 5, "y": 50}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: natural
      stroke: "#16a085"
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 3
      fill: "#16a085"

Characteristics:

  • Minimal curvature at endpoints
  • Natural-looking curves
  • Good for scientific data
  • Reduces overshoot at boundaries

Monotone Curves ​

Monotone X ​

Preserves monotonicity in x-direction:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 10},
      {"x": 1, "y": 15},
      {"x": 2, "y": 25},
      {"x": 3, "y": 28},
      {"x": 4, "y": 40},
      {"x": 5, "y": 45}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: monotone-x
      stroke: "#d35400"
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 3
      fill: "#d35400"

Use Cases:

  • Monotonically increasing/decreasing data
  • Financial charts (prices always go up or down)
  • Prevents artificial peaks and valleys
  • Maintains data trends

Monotone Y ​

Preserves monotonicity in y-direction:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 10},
      {"x": 1, "y": 20},
      {"x": 2, "y": 15},
      {"x": 3, "y": 30},
      {"x": 4, "y": 25},
      {"x": 5, "y": 40}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: monotone-y
      stroke: "#c0392b"
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 3
      fill: "#c0392b"

Use Cases:

  • Horizontal trends
  • Time series with guaranteed monotonicity
  • Growth/decay patterns

Bump Curves ​

Bump X ​

Creates smooth horizontal transitions:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 20},
      {"x": 1, "y": 40},
      {"x": 2, "y": 30},
      {"x": 3, "y": 50},
      {"x": 4, "y": 35}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: bump-x
      stroke: "#8e44ad"
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 4
      fill: "#8e44ad"

Use Cases:

  • Sankey-style diagrams
  • Flow charts
  • Ranking changes over time
  • Horizontal emphasis

Bump Y ​

Creates smooth vertical transitions:

data-glass
data:
  source: |
    [
      {"x": 0, "y": 20},
      {"x": 1, "y": 40},
      {"x": 2, "y": 30},
      {"x": 3, "y": 50},
      {"x": 4, "y": 35}
    ]
width: 600
height: 350
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: bump-y
      stroke: "#2980b9"
      strokeWidth: 2
  - type: dot
    configuration:
      x: x
      y: y
      r: 4
      fill: "#2980b9"

Use Cases:

  • Vertical flow diagrams
  • Stream graphs
  • Vertical ranking changes

Area Curves ​

Smooth Area Chart ​

Apply curves to area marks for smooth fills:

data-glass
data:
  source: |
    [
      {"date": "2024-01", "value": 100},
      {"date": "2024-02", "value": 130},
      {"date": "2024-03", "value": 115},
      {"date": "2024-04", "value": 145},
      {"date": "2024-05", "value": 160},
      {"date": "2024-06", "value": 150}
    ]
width: 600
height: 350
marks:
  - type: area
    configuration:
      x: date
      y: value
      curve: catmull-rom
      fill: steelblue
      fillOpacity: 0.4
  - type: line
    configuration:
      x: date
      y: value
      curve: catmull-rom
      stroke: steelblue
      strokeWidth: 2

Area Curve Tips:

  • Match curve type between area and line marks
  • Smooth curves create more organic appearance
  • Good for highlighting trends

Curve Comparison ​

Side-by-Side Comparison ​

Compare multiple curve types:

data-glass
data:
  source: |
    [
      {"x": 0, "linear": 20, "basis": 20, "monotone": 20},
      {"x": 1, "linear": 35, "basis": 35, "monotone": 35},
      {"x": 2, "linear": 25, "basis": 25, "monotone": 25},
      {"x": 3, "linear": 45, "basis": 45, "monotone": 45},
      {"x": 4, "linear": 30, "basis": 30, "monotone": 30}
    ]
width: 600
height: 350
scales:
  color:
    legend: true
marks:
  - type: line
    configuration:
      x: x
      y: linear
      curve: linear
      stroke: red
      strokeWidth: 2
  - type: line
    configuration:
      x: x
      y: basis
      curve: basis
      stroke: blue
      strokeWidth: 2
  - type: line
    configuration:
      x: x
      y: monotone
      curve: monotone-x
      stroke: green
      strokeWidth: 2

Best Practices ​

Curve Selection Guide ​

Choose Linear When:

  • Data has sharp transitions
  • Precision is critical
  • Interpolation would be misleading
  • Performance is a concern

Choose Step When:

  • Data represents discrete states
  • Values are constant between observations
  • Digital signals or categorical changes

Choose Smooth (Basis/Catmull-Rom) When:

  • Aesthetic appearance matters
  • Underlying process is continuous
  • Minor overshooting is acceptable
  • Presentation over precision

Choose Monotone When:

  • Data must preserve increasing/decreasing trends
  • Financial or scientific accuracy needed
  • Artificial peaks/valleys would be misleading

Choose Bump When:

  • Creating flow diagrams
  • Sankey-style visualizations
  • Emphasizing smooth transitions
  • Ranking or hierarchy changes

Performance Considerations ​

Rendering Speed ​

Fastest to Slowest:

  1. Linear - Simple line segments
  2. Step - Horizontal/vertical segments only
  3. Monotone - Constrained cubic interpolation
  4. Basis - Cubic B-splines
  5. Cardinal/Catmull-Rom - Complex spline calculations
  6. Natural - Matrix operations for boundary conditions

Optimization Tips:

  • Use linear for >1000 points
  • Consider data sampling for smooth curves
  • Test performance with your data size

Common Patterns ​

1. Smooth Time Series ​

yaml
marks:
  - type: line
    configuration:
      x: date
      y: value
      curve: catmull-rom  # Smooth, passes through points

2. Step Function ​

yaml
marks:
  - type: line
    configuration:
      x: time
      y: state
      curve: step-after  # Constant until next value

3. Monotonic Growth ​

yaml
marks:
  - type: line
    configuration:
      x: date
      y: cumulative
      curve: monotone-x  # Always increasing

4. Natural Scientific Data ​

yaml
marks:
  - type: line
    configuration:
      x: measurement
      y: result
      curve: natural  # Minimal endpoint curvature

Curve Type Reference ​

Curve TypePasses Through PointsSmoothnessBest For
linear✅ YesNoneDefault, precise data
step✅ YesNoneDiscrete states
step-after✅ YesNoneState changes
step-before✅ YesNoneLeading indicators
basis❌ NoVery HighAesthetic smoothing
cardinal✅ YesHighSmooth interpolation
catmull-rom✅ YesHighGeneral smoothing
natural✅ YesHighScientific data
monotone-x✅ YesMediumMonotonic trends
monotone-y✅ YesMediumHorizontal trends
bump-x✅ YesMediumFlow diagrams
bump-y✅ YesMediumVertical flows

Troubleshooting ​

Problem: Curve overshoots data points

  • Solution: Use monotone-x or monotone-y instead
  • Alternative: Use natural for minimal endpoint overshoot

Problem: Curve doesn't pass through points

  • Solution: Avoid basis - use catmull-rom or cardinal
  • Check: Verify curve spelling is correct

Problem: Jagged appearance with smooth curve

  • Solution: Increase data density or simplify curve type
  • Check: Ensure sufficient data points (minimum 3-4)

Problem: Performance issues

  • Solution: Use linear or reduce data points
  • Consider: Sampling data before visualization

Advanced Techniques ​

Custom Tension ​

Some curves support tension parameters (via Observable Plot options):

yaml
# Catmull-Rom with custom tension
marks:
  - type: line
    configuration:
      x: x
      y: y
      curve: catmull-rom
      tension: 0.5  # 0 = cardinal, 1 = tight

Mixed Curves ​

Use different curves for different series:

yaml
marks:
  - type: line  # Smooth primary trend
    configuration:
      x: date
      y: actual
      curve: catmull-rom
  - type: line  # Sharp forecast
    configuration:
      x: date
      y: forecast
      curve: linear

  • Text Annotations - Label curve peaks and valleys
  • Stacked Areas - Apply curves to stacked area charts
  • Error Bars - Combine curves with confidence intervals

Last Updated: 2025-01-12Part of Phase 3: Advanced Mark Types

Released under the MIT License. Built by Boundary Lab.