-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add first draft of pseudo hilbert curve
- Loading branch information
1 parent
f27b78b
commit ffce964
Showing
11 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
...153-astro-svelte/src/components/projects/graphics/pseudo-hilbert-curve/ProjectRoot.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<script lang="ts"> | ||
import { onMount } from 'svelte'; | ||
import { PseudoHilbertCurveGame, CanvasWrapperImpl } from '@vighnesh153/graphics-programming'; | ||
let canvasElement: HTMLCanvasElement; | ||
let game: PseudoHilbertCurveGame; | ||
onMount(() => { | ||
const canvasWrapper = new CanvasWrapperImpl(canvasElement); | ||
game = new PseudoHilbertCurveGame(canvasWrapper); | ||
const frames = game.start(); | ||
function showNextFrame() { | ||
if (!frames.next().done) { | ||
requestAnimationFrame(showNextFrame); | ||
} | ||
} | ||
showNextFrame(); | ||
}); | ||
</script> | ||
|
||
<canvas class="mt-6 mx-auto w-full max-w-3xl aspect-video bg-text" bind:this={canvasElement}> | ||
Sorry your browser doesn't support the canvas element | ||
</canvas> |
21 changes: 21 additions & 0 deletions
21
...dejs-apps/vighnesh153-astro-svelte/src/pages/projects/graphics/pseudo-hilbert-curve.astro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--- | ||
import { graphicsProjectsMap } from '@vighnesh153/graphics-programming'; | ||
import { classes, verifyGraphicsProjectPath } from '@/utils'; | ||
import { projectNavItems } from '@/constants'; | ||
import ContentLayout from '@/layouts/ContentLayout.astro'; | ||
import ProjectRoot from '@/components/projects/graphics/pseudo-hilbert-curve/ProjectRoot.svelte'; | ||
const project = graphicsProjectsMap.pseudoHilbertCurve; | ||
verifyGraphicsProjectPath(project, Astro.request.url); | ||
const title = `Vighnesh Raut | Graphics Projects - Pseudo Hilbert Curve`; | ||
const description = `A Hilbert curve is a continuous fractal space-filling curve`; | ||
--- | ||
|
||
<ContentLayout title={title} description={description} navItems={projectNavItems} showFooter={false}> | ||
<div class={classes(`mt-28 mb-12 max-w-xl mx-auto lg:max-w-[unset] scroll-mt-8`)}> | ||
<h1 class="text-3xl mb-6 text-center">Pseudo Hilbert Curve</h1> | ||
<ProjectRoot client:load /> | ||
</div> | ||
</ContentLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
nodejs-tools/nodejs-lib/graphics-programming/src/pseudo-hilbert-curve/Game.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { CanvasWrapper } from '@/canvas-wrapper'; | ||
import { generateCurve } from './generateCurve'; | ||
import { Point } from './point'; | ||
import { Line } from './line'; | ||
|
||
export class PseudoHilbertCurveGame { | ||
#canvasWrapper: CanvasWrapper; | ||
|
||
constructor(canvasWrapper: CanvasWrapper) { | ||
this.#canvasWrapper = canvasWrapper; | ||
} | ||
|
||
*start() { | ||
for (const level of [3]) { | ||
const p1 = new Point(100, 100); | ||
const p2 = new Point(100, 200); | ||
const p3 = new Point(200, 200); | ||
const p4 = new Point(200, 100); | ||
const curves = generateCurve(p1, p2, p3, p4, level); | ||
|
||
this.drawLines(curves); | ||
} | ||
|
||
yield; | ||
} | ||
|
||
private drawLines(lines: Line[]): void { | ||
for (const line of lines) { | ||
this.#canvasWrapper.drawLine(line.point1.x, line.point1.y, line.point2.x, line.point2.y, 2, 'black'); | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
nodejs-tools/nodejs-lib/graphics-programming/src/pseudo-hilbert-curve/euclidian-distance.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { range } from '@vighnesh153/utils'; | ||
|
||
export function euclidianDistance(point1: number[], point2: number[]): number { | ||
if (point1.length !== point2.length) { | ||
throw new Error(`Point dimensions are not the same. Dimension1=${point1.length}, Dimension2=${point2.length}`); | ||
} | ||
const squared = Array.from(range(0, point1.length - 1)) | ||
.map((index) => { | ||
const diff = Math.abs(point1[index] - point2[index]); | ||
return diff * diff; | ||
}) | ||
.reduce((prev, curr) => prev + curr, 0); | ||
return Math.sqrt(squared); | ||
} |
63 changes: 63 additions & 0 deletions
63
nodejs-tools/nodejs-lib/graphics-programming/src/pseudo-hilbert-curve/generateCurve.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { generateTwoMidPoints } from './generateTwoMidpoints'; | ||
import { getDistantCorner } from './getDistantCorner'; | ||
import { Line } from './line'; | ||
import { Point } from './point'; | ||
|
||
/** | ||
* | ||
* c1---------a b---------c4 | ||
* | | | ||
* p1 | | p4 | ||
* | | | | | ||
* c----------i j---------e | ||
* | | | | | ||
* | | | | | ||
* | | | | | ||
* d | k----------l | f | ||
* | | | | | | | ||
* | p2----|----------|----p3 | | ||
* | | | | | ||
* c2---------g h---------c3 | ||
* | ||
*/ | ||
export function generateCurve(p1: Point, p2: Point, p3: Point, p4: Point, level: number): Line[] { | ||
if (level < 1) { | ||
throw new Error('Level cannot be less than 1'); | ||
} | ||
if (level === 1) return [new Line(p1, p2), new Line(p2, p3), new Line(p3, p4)]; | ||
|
||
// corners | ||
const c1 = getDistantCorner(p1, p2, p4); | ||
const c2 = getDistantCorner(p2, p3, p1); | ||
const c3 = getDistantCorner(p3, p4, p2); | ||
const c4 = getDistantCorner(p4, p1, p3); | ||
|
||
// return [new Line(c1, c2), new Line(c2, c3), new Line(c3, c4)]; | ||
|
||
// mid points | ||
const { midPoint1: c, midPoint2: d } = generateTwoMidPoints(c1, c2); | ||
const { midPoint1: g, midPoint2: h } = generateTwoMidPoints(c2, c3); | ||
const { midPoint1: f, midPoint2: e } = generateTwoMidPoints(c3, c4); | ||
const { midPoint1: b, midPoint2: a } = generateTwoMidPoints(c4, c1); | ||
const { midPoint1: i, midPoint2: k } = generateTwoMidPoints(a, g); | ||
const { midPoint1: j, midPoint2: l } = generateTwoMidPoints(b, h); | ||
|
||
// curve near p1 | ||
const p1Curve = generateCurve(c, i, a, c1, level - 1); | ||
// curve near p2 | ||
const p2Curve = generateCurve(d, c2, g, k, level - 1); | ||
// curve near p3 | ||
const p3Curve = generateCurve(l, h, c3, f, level - 1); | ||
// curve near p3 | ||
const p4Curve = generateCurve(c4, b, j, e, level - 1); | ||
|
||
return [ | ||
...p1Curve.toReversed(), | ||
new Line(p1Curve[0].point1, p2Curve[0].point1), | ||
...p2Curve, | ||
new Line(p2Curve[p2Curve.length - 1].point2, p3Curve[0].point1), | ||
...p3Curve, | ||
new Line(p3Curve[p3Curve.length - 1].point2, p4Curve[p3Curve.length - 1].point2), | ||
...p4Curve.toReversed(), | ||
]; | ||
} |
33 changes: 33 additions & 0 deletions
33
...js-tools/nodejs-lib/graphics-programming/src/pseudo-hilbert-curve/generateTwoMidpoints.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Point } from './point'; | ||
|
||
interface TwoMidpoints { | ||
midPoint1: Point; | ||
midPoint2: Point; | ||
} | ||
|
||
export function generateTwoMidPoints(startPoint: Point, endPoint: Point): TwoMidpoints { | ||
const isXDifferent = startPoint.x !== endPoint.x; | ||
|
||
// one of distX or distY will be 0 | ||
const distX = Math.abs(startPoint.x - endPoint.x); | ||
const distY = Math.abs(startPoint.y - endPoint.y); | ||
const dist = (isXDifferent ? distX : distY) / 3; | ||
|
||
const start = isXDifferent ? startPoint.x : startPoint.y; | ||
const end = isXDifferent ? endPoint.x : endPoint.y; | ||
const sign = start < end ? 1 : -1; | ||
|
||
const midPoint1 = Math.round(start + sign * dist); | ||
const midPoint2 = Math.round(start + sign * dist * 2); | ||
|
||
if (isXDifferent) { | ||
return { | ||
midPoint1: new Point(midPoint1, startPoint.y), | ||
midPoint2: new Point(midPoint2, startPoint.y), | ||
}; | ||
} | ||
return { | ||
midPoint1: new Point(startPoint.x, midPoint1), | ||
midPoint2: new Point(startPoint.x, midPoint2), | ||
}; | ||
} |
51 changes: 51 additions & 0 deletions
51
nodejs-tools/nodejs-lib/graphics-programming/src/pseudo-hilbert-curve/getDistantCorner.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* eslint-disable @typescript-eslint/no-use-before-define */ | ||
import { euclidianDistance } from './euclidian-distance'; | ||
import { Point } from './point'; | ||
|
||
// repel -> as in repel like a magnet | ||
export function getDistantCorner(point: Point, repelPoint1: Point, repelPoint2: Point): Point { | ||
const distance = euclidianDistance([point.x, point.y], [repelPoint1.x, repelPoint1.y]) / 4; | ||
|
||
const potentialPoints = [ | ||
new Point(point.x + distance, point.y + distance), | ||
new Point(point.x + distance, point.y - distance), | ||
new Point(point.x - distance, point.y + distance), | ||
new Point(point.x - distance, point.y - distance), | ||
]; | ||
|
||
const farthestPointsFromRepelPoint1 = findFarthestPoints(repelPoint1, potentialPoints); | ||
const farthestPointsFromRepelPoint2 = findFarthestPoints(repelPoint2, potentialPoints); | ||
|
||
const intersection = findIntersectionPoints(farthestPointsFromRepelPoint1, farthestPointsFromRepelPoint2); | ||
|
||
if (intersection.length !== 1) { | ||
throw new Error('intersection length should be 1'); | ||
} | ||
|
||
return intersection[0]; | ||
} | ||
|
||
function findFarthestPoints(pivotPoint: Point, points: Point[]): Point[] { | ||
let farthestPoints: Point[] = []; | ||
let maxDistance = 0; | ||
for (const point of points) { | ||
const dist = euclidianDistance([point.x, point.y], [pivotPoint.x, pivotPoint.y]); | ||
if (dist > maxDistance) { | ||
maxDistance = dist; | ||
farthestPoints = [point]; | ||
} else if (dist === maxDistance) { | ||
farthestPoints.push(point); | ||
} | ||
} | ||
return farthestPoints; | ||
} | ||
|
||
function findIntersectionPoints(list1: Point[], list2: Point[]): Point[] { | ||
const common: Point[] = []; | ||
for (const point of list1) { | ||
if (list2.includes(point)) { | ||
common.push(point); | ||
} | ||
} | ||
return common; | ||
} |
1 change: 1 addition & 0 deletions
1
nodejs-tools/nodejs-lib/graphics-programming/src/pseudo-hilbert-curve/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { PseudoHilbertCurveGame } from './Game'; |
11 changes: 11 additions & 0 deletions
11
nodejs-tools/nodejs-lib/graphics-programming/src/pseudo-hilbert-curve/line.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { Point } from './point'; | ||
|
||
export class Line { | ||
readonly point1: Point; | ||
readonly point2: Point; | ||
|
||
constructor(point1: Point, point2: Point) { | ||
this.point1 = point1; | ||
this.point2 = point2; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
nodejs-tools/nodejs-lib/graphics-programming/src/pseudo-hilbert-curve/point.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export class Point { | ||
readonly x: number; | ||
readonly y: number; | ||
|
||
constructor(x: number, y: number) { | ||
this.x = x; | ||
this.y = y; | ||
} | ||
|
||
clone(): Point { | ||
return new Point(this.x, this.y); | ||
} | ||
} |