Skip to content

Commit

Permalink
refactor: only use a single size value for all computations
Browse files Browse the repository at this point in the history
Replaces the inputValues triangleHeight and triangleBase as they were always the same.
  • Loading branch information
JanMalch committed Nov 14, 2020
1 parent 916f0eb commit 83cc2c1
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 96 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [x] use strict TypeScript mode
- [x] fix mobile layout
- [x] in mem canvas
- [ ] remove `inputValues`: base and height are always the same
- [x] remove `inputValues`: base and height are always the same
- [x] find good default size (to match A4 paper)
- [x] scale preview nicely into viewport
- [ ] code improvements
Expand Down
22 changes: 3 additions & 19 deletions __tests__/formulas/util.test.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
import { p } from '../../src/factories';
import { scale, scaleTriangle } from '../../src/formulas/util';
import type { InputValues } from '../../src/types';

describe('scale', () => {
const values: InputValues = { triangleBase: 2, triangleHeight: 2 };
it('should move the point correctly', () => {
expect(scale(p(0, 0))(values)).toEqual(p(0, 0));
expect(scale(p(1, 1))(values)).toEqual(p(2, 2));
expect(scale(p(1, 1))({ triangleBase: 2, triangleHeight: 0 })).toEqual(
p(0, 2)
);
expect(scale(p(0, 0))(2)).toEqual(p(0, 0));
expect(scale(p(1, 1))(2)).toEqual(p(2, 2));
});
});

describe('scaleTriangle', () => {
const values: InputValues = {
triangleBase: 2,
triangleHeight: 2,
};
it('should move the point correctly', () => {
expect(scaleTriangle([p(0, 0), p(0, 1), p(1, 1)])(values)).toEqual([
expect(scaleTriangle([p(0, 0), p(0, 1), p(1, 1)])(2)).toEqual([
p(0, 0),
p(0, 2),
p(2, 2),
]);

expect(
scaleTriangle([p(0, 0), p(0, 1), p(1, 1)])({
triangleBase: 2,
triangleHeight: 1,
})
).toEqual([p(0, 0), p(0, 2), p(1, 2)]);
});
});
7 changes: 4 additions & 3 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
import FileInputs from './components/FileInputs.svelte';
import Canvas from './components/Canvas.svelte';
const size = 200;
let canvasSection: HTMLElement;
let canvasComponent: any & { canvas: HTMLCanvasElement };
let triangleHeight = 200;
let previewVisible = false;
Expand Down Expand Up @@ -68,7 +69,7 @@
note that the cutting is based on the largest possible hexagon in the center
of each image. To make sure you have the desired outcome, you can upload
squared images that are at least
{triangleHeight}×{triangleHeight}px in size.
{size}×{size}px in size.
</p>
<p>
Simply select four images with the boxes below. If you select more than one
Expand Down Expand Up @@ -115,7 +116,7 @@
drawables="{imageElements}"
drawCuttingLines="{drawCuttingLines}"
drawFoldingLines="{drawFoldingLines}"
triangleHeight="{triangleHeight}"
size="{size}"
on:finish="{onFinish}" />
</section>
<section>
Expand Down
51 changes: 24 additions & 27 deletions src/components/Canvas.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,15 @@
import type { Point } from '../types';
export let drawables: HTMLImageElement[] = [];
export let triangleHeight: number;
export let size: number;
export let canvas: HTMLCanvasElement | null = null;
export let drawCuttingLines = false;
export let drawFoldingLines = false;
const dispatch = createEventDispatcher();
$: ctx = canvas?.getContext('2d')!;
$: triangleBase = triangleHeight;
$: inputValues = { triangleBase, triangleHeight };
$: glueWidth = Math.ceil(triangleHeight * 0.4);
$: glueWidth = Math.ceil(size * 0.4);
$: {
if (
Expand All @@ -34,7 +31,7 @@
) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawGlue(ctx, inputValues, glueWidth);
drawGlue(ctx, size, glueWidth);
const allTriangleSetups = drawables.map((drawable) =>
Array(6)
Expand All @@ -53,7 +50,7 @@
for (let i = 0; i < triangleSelectors.length; i++) {
const setup = triangleSetups[i];
const result = extractRotatedTriangle(
inputValues,
size,
setup.image,
setup.clippingTriangle,
setup.relativeRectangle,
Expand All @@ -80,21 +77,21 @@
ctx.beginPath();
ctx.moveTo(0, 0);
// bottom zic zac
ctx.lineTo(0, triangleHeight * 2);
ctx.lineTo(triangleBase, triangleHeight * 2.5);
ctx.lineTo(triangleBase * 2, triangleHeight * 2);
ctx.lineTo(triangleBase * 3, triangleHeight * 2.5);
ctx.lineTo(triangleBase * 4, triangleHeight * 2);
ctx.lineTo(triangleBase * 5, triangleHeight * 2.5);
ctx.lineTo(triangleBase * 6, triangleHeight * 2);
ctx.lineTo(0, size * 2);
ctx.lineTo(size, size * 2.5);
ctx.lineTo(size * 2, size * 2);
ctx.lineTo(size * 3, size * 2.5);
ctx.lineTo(size * 4, size * 2);
ctx.lineTo(size * 5, size * 2.5);
ctx.lineTo(size * 6, size * 2);
// around glue
const yDiff = Math.tan(degreeToRadian(90 - magicAngle)) * glueWidth;
ctx.lineTo(triangleBase * 6 + glueWidth, triangleHeight * 2 - yDiff);
ctx.lineTo(triangleBase * 6 + glueWidth, triangleHeight + yDiff);
ctx.lineTo(triangleBase * 6, triangleHeight);
ctx.lineTo(triangleBase * 6 + glueWidth, triangleHeight - yDiff);
ctx.lineTo(triangleBase * 6 + glueWidth, yDiff);
ctx.lineTo(triangleBase * 6, 0);
ctx.lineTo(size * 6 + glueWidth, size * 2 - yDiff);
ctx.lineTo(size * 6 + glueWidth, size + yDiff);
ctx.lineTo(size * 6, size);
ctx.lineTo(size * 6 + glueWidth, size - yDiff);
ctx.lineTo(size * 6 + glueWidth, yDiff);
ctx.lineTo(size * 6, 0);
ctx.closePath();
Expand All @@ -106,8 +103,8 @@
const drawLine = ({ start, end }: { start: Point; end: Point }) => {
ctx.beginPath();
ctx.moveTo(triangleHeight * start.x, triangleBase * start.y);
ctx.lineTo(triangleHeight * end.x, triangleBase * end.y);
ctx.moveTo(size * start.x, size * start.y);
ctx.lineTo(size * end.x, size * end.y);
ctx.stroke();
};
Expand All @@ -131,20 +128,20 @@
ctx.drawImage(
partialCanvas,
5 * partialCanvas.width,
line * (triangleBase / 2)
line * (size / 2)
);
} else {
ctx.drawImage(
partialCanvas,
(index - 1) * partialCanvas.width,
line * (triangleBase / 2)
line * (size / 2)
);
}
} else {
ctx.drawImage(
partialCanvas,
index * partialCanvas.width,
line * (triangleBase / 2)
line * (size / 2)
);
}
}
Expand All @@ -154,8 +151,8 @@

<canvas
class="box-shadow"
width="{triangleHeight * 6 + glueWidth}"
height="{triangleBase * 2.5}"
width="{size * 6 + glueWidth}"
height="{size * 2.5}"
bind:this="{canvas}"></canvas>

<style>
Expand Down
8 changes: 4 additions & 4 deletions src/drawing/glue.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { p } from '../factories';
import { glueSideParts, glueTopParts } from '../formulas/glue';
import type { InputValues, Point, Triangle } from '../types';
import type { Point, Triangle } from '../types';
import { moveAlongPath } from './utils';

/**
Expand Down Expand Up @@ -42,11 +42,11 @@ export function drawGlueArea(

export function drawGlue(
ctx: CanvasRenderingContext2D,
inputValues: InputValues,
size: number,
glueWidth: number
) {
const topParts = glueTopParts(inputValues);
const sideParts = glueSideParts(inputValues);
const topParts = glueTopParts(size);
const sideParts = glueSideParts(size);

for (const topPart of topParts) {
drawGlueArea(
Expand Down
16 changes: 8 additions & 8 deletions src/drawing/processing.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { magicHeight } from '../formulas/content';
import { degreeToRadian } from '../formulas/math';
import type { InputValues, NaturalImage, ProcessingOptions, Rectangle, RectangleDef, TriangleDef } from '../types';
import type { NaturalImage, ProcessingOptions, Rectangle, RectangleDef, TriangleDef } from '../types';
import { drawImage, inClip } from './utils';

/**
Expand Down Expand Up @@ -181,22 +181,22 @@ function createCanvas(dimensions: RectangleDef): HTMLCanvasElement {
return canvas;
}

export function extractRotatedTriangle(inputValues: InputValues,
export function extractRotatedTriangle(size: number,
image: NaturalImage & CanvasImageSource,
clippingTriangle: TriangleDef,
relativeRectangle: Rectangle,
rotation: ProcessingOptions["rotation"]) {
const toTriangleCanvas = createCanvas({
width: inputValues.triangleBase,
height: inputValues.triangleHeight * (magicHeight * 2),
width: size,
height: size * (magicHeight * 2),
});
const rotatedTriangleCanvas = createCanvas({
height: inputValues.triangleBase,
width: inputValues.triangleHeight * (magicHeight * 2),
height: size,
width: size * (magicHeight * 2),
});
const scaledRotatedTriangleCanvas = createCanvas({
width: inputValues.triangleBase,
height: inputValues.triangleHeight,
width: size,
height: size,
});

loadIntoTriangleCanvas(toTriangleCanvas, image, clippingTriangle, relativeRectangle);
Expand Down
30 changes: 15 additions & 15 deletions src/formulas/glue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { p } from '../factories';
import type { InputValues, Triangle } from '../types';
import type { Triangle } from '../types';
import { scaleTriangle } from './util';

const topGlueTriangle = scaleTriangle([p(0, 0), p(1, 0.5), p(2, 0)]);
Expand All @@ -8,26 +8,26 @@ const topGlueTriangle = scaleTriangle([p(0, 0), p(1, 0.5), p(2, 0)]);
* Calculates the glue parts on top as a triangle, that can later be cut off.
*
* The triangle has the relative points `[(0, 0), (1, 0.5), (2, 0)]`.
* @param values
* @param size the base size
*/
export function glueTopParts(
values: InputValues
size: number
): [Triangle, Triangle, Triangle] {
return [
{
x: 0,
y: 0,
points: topGlueTriangle(values),
points: topGlueTriangle(size),
},
{
x: values.triangleHeight * 2,
x: size * 2,
y: 0,
points: topGlueTriangle(values),
points: topGlueTriangle(size),
},
{
x: values.triangleHeight * 4,
x: size * 4,
y: 0,
points: topGlueTriangle(values),
points: topGlueTriangle(size),
},
];
}
Expand All @@ -38,19 +38,19 @@ const sideGlueTriangle = scaleTriangle([p(0, 0), p(0, 1), p(1, 0.5)]);
* Calculates the glue parts on the side as a triangle, that can later be cut off.
*
* The triangle has the relative points `[(0, 0), (0, 1), (1, 0.5)]`.
* @param values
* @param size the base size
*/
export function glueSideParts(values: InputValues): [Triangle, Triangle] {
export function glueSideParts(size: number): [Triangle, Triangle] {
return [
{
x: values.triangleHeight * 6,
x: size * 6,
y: 0,
points: sideGlueTriangle(values),
points: sideGlueTriangle(size),
},
{
x: values.triangleHeight * 6,
y: values.triangleBase,
points: sideGlueTriangle(values),
x: size * 6,
y: size,
points: sideGlueTriangle(size),
},
];
}
20 changes: 9 additions & 11 deletions src/formulas/util.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import type { InputValues, Point, TriangleDef } from '../types';
import type { Point, TriangleDef } from '../types';

/**
* Moves the given point by multiplying
* - the `x` coordinate with the `CoreValues#triangleHeight`
* - and the `y` coordinate with the `CoreValues#triangleBase`
* Moves the given point by multiplying both coordinates with the `size`.
* @param point the point to move
*/
export function scale(point: Point): (values: InputValues) => Point {
return (values) => ({
x: point.x * values.triangleHeight,
y: point.y * values.triangleBase,
export function scale(point: Point): (size: number) => Point {
return (size) => ({
x: point.x * size,
y: point.y * size,
});
}

Expand All @@ -20,8 +18,8 @@ export function scale(point: Point): (values: InputValues) => Point {
*/
export function scaleTriangle(
triangle: TriangleDef
): (values: InputValues) => TriangleDef {
return (values: InputValues) => {
return triangle.map((p) => scale(p)(values)) as TriangleDef;
): (size: number) => TriangleDef {
return (size: number) => {
return triangle.map((p) => scale(p)(size)) as TriangleDef;
};
}
8 changes: 0 additions & 8 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ export interface RectangleDef {
*/
export type Rectangle = Point & RectangleDef;

/**
* The original input values that only computations rely on.
*/
export interface InputValues {
triangleBase: number;
triangleHeight: number;
}

/**
* An image with the natural (original) width and height preserved.
*/
Expand Down

0 comments on commit 83cc2c1

Please sign in to comment.