Skip to content

Commit

Permalink
feat: Add support for multidimensional springs
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Update function exports to use @thi.ng/vectors for
  • Loading branch information
nonphoto committed Sep 8, 2024
1 parent 0547d8c commit 8fa2a23
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 74 deletions.
20 changes: 8 additions & 12 deletions examples/canvas/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
springCreate,
springDuration,
springPosition,
} from "@nonphoto/spring/src/index";
import { durationN, fromOptions, positionN } from "@nonphoto/spring/src/index";
import { createWindowSize } from "@solid-primitives/resize-observer";
import { createEffect } from "solid-js";

Expand All @@ -26,32 +22,32 @@ export default function () {

const step = 2;

const spring = springCreate({
start: h(),
end: h() / 3,
const spring = fromOptions({
start: [h()],
end: [h() / 3],
halflife: w() * 0.1,
});

const context = canvas.getContext("2d")!;
context.lineWidth = 2;

context.beginPath();
context.moveTo(0, spring.end);
context.lineTo(w(), spring.end);
context.moveTo(0, spring.end[0]);
context.lineTo(w(), spring.end[0]);
context.strokeStyle = "lightgray";
context.stroke();

context.beginPath();
context.moveTo(0, h());
for (let x = 0; x < w(); x += step) {
const y = springPosition(spring, x);
const y = positionN(spring, x);
context.lineTo(x, y);
}
context.strokeStyle = "#0000ff";
context.stroke();

context.beginPath();
const x = springDuration(spring, 1);
const x = durationN(spring, 1);
console.log(spring);
context.moveTo(x, 0);
context.lineTo(x, h());
Expand Down
4 changes: 4 additions & 0 deletions packages/spring/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@
"author": "Jonas Luebbers",
"license": "MIT",
"devDependencies": {
"@thi.ng/vectors": "7.12.0",
"semantic-release": "24.1.0",
"tsup": "8.2.4",
"typescript": "5.5.4"
},
"engines": {
"node": ">=20",
"pnpm": ">=9"
},
"peerDependencies": {
"@thi.ng/vectors": "7.12.0"
}
}
4 changes: 2 additions & 2 deletions packages/spring/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from "./math";
export * from "./spring";
export * from "./math.js";
export * from "./spring.js";
32 changes: 19 additions & 13 deletions packages/spring/src/math.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,61 @@
export function mix(x: number, y: number, a: number) {
export function mix(x: number, y: number, a: number): number {
return (1 - a) * x + a * y;
}

export function copySign(x: number, y: number) {
export function copySign(x: number, y: number): number {
return Math.sign(x) === Math.sign(y) ? x : -x;
}

export function square(x: number) {
export function square(x: number): number {
return x * x;
}

export function fastNegExp(x: number) {
export function fastNegExp(x: number): number {
return 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);
}

export function fastAtan(x: number) {
export function fastAtan(x: number): number {
const z = Math.abs(x);
const w = z > 1 ? 1 / z : z;
const y = (Math.PI / 4) * w - w * (w - 1) * (0.2447 + 0.0663 * w);
return copySign(z > 1 ? Math.PI / 2 - y : y, x);
}

export function halflifeToDamping(halflife: number) {
export function halflifeToDamping(halflife: number): number {
return (4 * Math.LN2) / halflife;
}

export function dampingToHalflife(damping: number) {
export function dampingToHalflife(damping: number): number {
return (4 * Math.LN2) / damping;
}

export function frequencyToStiffness(frequency: number) {
export function frequencyToStiffness(frequency: number): number {
return square(2 * Math.PI * frequency);
}

export function stiffnessToFrequency(stiffness: number) {
export function stiffnessToFrequency(stiffness: number): number {
return Math.sqrt(stiffness) / (2 * Math.PI);
}

export function criticalHalflife(frequency: number) {
export function criticalHalflife(frequency: number): number {
return dampingToHalflife(Math.sqrt(frequencyToStiffness(frequency) * 4));
}

export function criticalFrequency(halflife: number) {
export function criticalFrequency(halflife: number): number {
return stiffnessToFrequency(square(halflifeToDamping(halflife)) / 4);
}

export function dampingRatioToStiffness(dampingRatio: number, damping: number) {
export function dampingRatioToStiffness(
dampingRatio: number,
damping: number
): number {
return square(damping / (dampingRatio * 2));
}

export function dampingRatioToDamping(dampingRatio: number, stiffness: number) {
export function dampingRatioToDamping(
dampingRatio: number,
stiffness: number
): number {
return dampingRatio * 2 * Math.sqrt(stiffness);
}

Expand Down
Loading

0 comments on commit 8fa2a23

Please sign in to comment.