Skip to content

Commit 4998396

Browse files
committed
replace all mod operations with the util
1 parent 8792feb commit 4998396

File tree

6 files changed

+20
-18
lines changed

6 files changed

+20
-18
lines changed

internal/animate/interpolate.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {Shape} from "../types";
2-
import {split, splitLine} from "../util";
2+
import {split, splitLine, mod} from "../util";
33

44
const interpolateAngle = (percentage: number, a: number, b: number): number => {
55
const tau = Math.PI * 2;
6-
let aNorm = ((a % tau) + tau) % tau;
7-
let bNorm = ((b % tau) + tau) % tau;
6+
let aNorm = mod(a, tau);
7+
let bNorm = mod(b, tau);
88
if (Math.abs(aNorm - bNorm) > Math.PI) {
99
if (aNorm < bNorm) {
1010
aNorm += tau;

internal/animate/prepare.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {copyPoint, length, reverse, shift, insertCount, distance} from "../util";
1+
import {copyPoint, length, reverse, shift, insertCount, distance, mod} from "../util";
22
import {Point, Shape} from "../types";
33

44
const optimizeOrder = (a: Shape, b: Shape): Shape => {
@@ -12,7 +12,7 @@ const optimizeOrder = (a: Shape, b: Shape): Shape => {
1212
for (let i = 0; i < count; i++) {
1313
let sum = 0;
1414
for (let j = 0; j < count; j++) {
15-
sum += distance(a[j], shape[(j + i) % count]);
15+
sum += distance(a[j], shape[mod(j + i, count)]);
1616
if (sum > minSum) break;
1717
}
1818
if (sum <= minSum) {
@@ -35,14 +35,14 @@ export const divideShape = (count: number, points: Shape): Shape => {
3535

3636
const lengths = [];
3737
for (let i = 0; i < points.length; i++) {
38-
lengths.push(length(points[i], points[(i + 1) % points.length]));
38+
lengths.push(length(points[i], points[mod(i + 1, points.length)]));
3939
}
4040

4141
const divisors = divideLengths(lengths, count - points.length);
4242
const out: Shape = [];
4343
for (let i = 0; i < points.length; i++) {
4444
const curr: Point = out[out.length - 1] || points[i];
45-
const next = points[(i + 1) % points.length];
45+
const next = points[mod(i + 1, points.length)];
4646
out.pop();
4747
out.push(...insertCount(divisors[i], curr, next));
4848
}

internal/render/canvas.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Coord, Shape} from "../types";
2-
import {expandHandle} from "../util";
2+
import {expandHandle, mod} from "../util";
33

44
const pointSize = 2;
55
const infoSpacing = 20;
@@ -37,7 +37,7 @@ export const drawShape = (ctx: CanvasRenderingContext2D, debug: boolean, shape:
3737
for (let i = 0; i < shape.length; i++) {
3838
// Compute coordinates of handles.
3939
const curr = shape[i];
40-
const next = shape[(i + 1) % shape.length];
40+
const next = shape[mod(i + 1, shape.length)];
4141
const currHandle = expandHandle(curr, curr.handleOut);
4242
const nextHandle = expandHandle(next, next.handleIn);
4343

internal/render/svg.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {xml, XmlElement} from "../../editable";
22
import {Shape} from "../types";
3-
import {expandHandle} from "../util";
3+
import {expandHandle, mod} from "../util";
44

55
export interface RenderOptions {
66
// Viewport size.
@@ -31,7 +31,7 @@ export const renderEditable = (points: Shape, opt: RenderOptions): XmlElement =>
3131
let path = `M${points[0].x},${points[0].y}`;
3232
for (let i = 0; i < points.length; i++) {
3333
const curr = points[i];
34-
const next = points[(i + 1) % points.length];
34+
const next = points[mod(i + 1, points.length)];
3535
const currControl = expandHandle(curr, curr.handleOut);
3636
const nextControl = expandHandle(next, next.handleIn);
3737
path += `C${currControl.x},${currControl.y},${nextControl.x},${nextControl.y},${next.x},${next.y}`;
@@ -80,7 +80,7 @@ export const renderEditable = (points: Shape, opt: RenderOptions): XmlElement =>
8080
// Points and handles.
8181
for (let i = 0; i < points.length; i++) {
8282
const curr = points[i];
83-
const next = points[(i + 1) % points.length];
83+
const next = points[mod(i + 1, points.length)];
8484
const currControl = expandHandle(curr, curr.handleOut);
8585
const nextControl = expandHandle(next, next.handleIn);
8686

internal/util.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export const shift = (offset: number, shape: Shape): Shape => {
5252
if (offset === 0) return shape;
5353
const out: Shape = [];
5454
for (let i = 0; i < shape.length; i++) {
55-
out.push(shape[(i + offset) % shape.length]);
55+
out.push(shape[mod(i + offset, shape.length)]);
5656
}
5757
return out;
5858
};
@@ -110,7 +110,7 @@ export const smooth = (shape: Shape, strength: number): Shape => {
110110
for (let i = 0; i < shape.length; i++) {
111111
const curr = shape[i];
112112
const before = shape[mod(i - 1, shape.length)];
113-
const after = shape[(i + 1) % shape.length];
113+
const after = shape[mod(i + 1, shape.length)];
114114
const angle = angleOf(before, after);
115115

116116
out.push({
@@ -130,6 +130,8 @@ export const smooth = (shape: Shape, strength: number): Shape => {
130130
return out;
131131
};
132132

133+
// Modulo operation that always produces a positive result.
134+
// https://stackoverflow.com/q/4467539/3053361
133135
export const mod = (a: number, n: number): number => {
134136
return ((a % n) + n) % n;
135137
};

testing/animate.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import blobs from "..";
33
import {interpolateBetweenLoop} from "../internal/animate/interpolate";
44
import {divideShape, prepShapes} from "../internal/animate/prepare";
55
import {Coord, Point, Shape} from "../internal/types";
6-
import {length, insertAt, insertCount, rad} from "../internal/util";
6+
import {length, insertAt, insertCount, rad, mod} from "../internal/util";
77
import {clear, drawInfo, drawShape} from "../internal/render/canvas";
88

99
const animationSpeed = 2;
@@ -40,15 +40,15 @@ const testSplitAt = (percentage: number) => {
4040
const stop = 2 * count - 1;
4141
for (let i = 0; i < count; i++) {
4242
const double = i * 2;
43-
const next = (double + 1) % stop;
43+
const next = mod(double + 1, stop);
4444
points.splice(double, 2, ...insertAt(percentage, points[double], points[next]));
4545
}
4646
points.splice(0, 1);
4747

4848
let sum = 0;
4949
for (let i = 0; i < points.length; i++) {
5050
const curr = points[i];
51-
const next = points[(i + 1) % points.length];
51+
const next = points[mod(i + 1, points.length)];
5252
sum += length(curr, next);
5353
}
5454
drawInfo(ctx, 1, "split at lengths sum", sum);
@@ -154,7 +154,7 @@ const genBlob = (
154154
testPrepShapesB(percentage);
155155

156156
percentage += animationSpeed / 1000;
157-
percentage %= 1;
157+
percentage = mod(percentage, 1);
158158
if (animationSpeed > 0) requestAnimationFrame(renderFrame);
159159
};
160160
renderFrame();

0 commit comments

Comments
 (0)