kjerandp / curve-interpolator

Interpolate values over a cubic Cardinal/Catmull-Rom curve
https://kjerandp.github.io/curve-interpolator/
MIT License
49 stars 6 forks source link

Tension and Alpha Options are Ignored in getPoints() Function #31

Open elsonel opened 1 year ago

elsonel commented 1 year ago

Hello,

I'm still getting loops and rounded curves if I try to draw a graph using the points generated in getPoints() even though tension and alpha are set to 0

image

This is the code I used to draw the graph using React.

import './App.css';
import { useEffect, useRef } from 'react';
import { CurveInterpolator } from 'curve-interpolator';

const CANVAS_WIDTH = 800;
const CANVAS_HEIGHT = 600;
const SEGMENTS = 1000;
const NUMBER_OF_CONTROL_POINTS = 10;

// Draw a straight line connecting all sorted points
function drawLinesThroughPoints(
  context: CanvasRenderingContext2D,
  points: [number, number][]
) {
  const [startX, startY] = points[0];

  context.beginPath();
  context.moveTo(startX, startY);
  for (let i = 1; i < points.length; i++) {
    const [x, y] = points[i];
    context.lineTo(x, y);
  }
  context.stroke();
}

// Generate a list of random points within the specified bounds
function generateSortedPoints(
  quantity: number,
  xLimit: number,
  yLimit: number
): number[][] {
  const points: number[][] = [];

  for (let i = 0; i < quantity; i++) {
    const x = Math.floor(Math.random() * xLimit);
    const y = Math.floor(Math.random() * yLimit);
    points.push([x, y]);
  }

  return points.sort((a, b) => {
    if (a[0] === b[0]) {
      return a[1] - b[1];
    } else {
      return a[0] - b[0];
    }
  });
}

// Render canvas
function App() {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const context = canvasRef.current?.getContext('2d');
    if (!context) return;

    // Get points
    const interp = new CurveInterpolator(
      generateSortedPoints(
        NUMBER_OF_CONTROL_POINTS,
        CANVAS_WIDTH,
        CANVAS_HEIGHT
      ),
      {
        tension: 0,
        alpha: 0,
      }
    );
    const points = interp.getPoints(SEGMENTS);

    // Draw curve on canvas
    context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    context.strokeStyle = 'red';
    context.lineWidth = 3;
    drawLinesThroughPoints(context, points);
  }, []);

  return (
    <div className="Wrapper">
      <canvas
        className="CurveCanvas"
        width={CANVAS_WIDTH}
        height={CANVAS_HEIGHT}
        ref={canvasRef}
      />
    </div>
  );
}

export default App;
kjerandp commented 1 year ago

Alpha should be set to 0.5 if you want to avoid loops. Tension = 0 gives you rounded curves, while tension = 1 should be close to linear interpolation.

elsonel commented 1 year ago

Hi @kjerandp, thanks for all the work you've done on the library.

Seems like I got the domain for tension reversed.

Does Tension = 0.5, and Alpha = 0.5 mean a rounded curve without any loops? Seems like I'm still occasionally getting loops with those parameters.

kjerandp commented 1 year ago

Alpha @ 0.5 is the important one. Tension may be left at 0, but may be increased if you want tighter curves.