Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: move out some code as workspaces #139

Merged
merged 4 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 9 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
{
"files.associations": {
"*.svx": "markdown"
"*.mdx": "markdown"
},
"eslint.validate": [
"javascript",
"typescript",
"svelte"
],
"cssVariables.lookupFiles": [
"src/lib/styles/tokens.css",
"src/lib/styles/theme-*.css"
]
"src/**/tokens.css",
"src/**/theme-*.css"
],
"search.exclude": {
"**/.svelte-kit": true,
"**/build": true
},
"cSpell.language": "en,ru,en-US,ru-RU"
}
4 changes: 4 additions & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module "*.module.css" {
const classes: { [key: string]: string };
export default classes;
}
44 changes: 44 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/apps/escapist-marginalia/mdsvex.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
const LAYOUT_PATH = "/src/lib/layout/default/default.layout.svelte";

export const mdsvexConfig = {
extensions: [ ".mdx" ],
remarkPlugins: [ transformerTOC, math, transformerMath ],
rehypePlugins: [ correct_hast_tree, rehype_katex, slug, transformerAnchor ],
layout: {
Expand Down
5 changes: 5 additions & 0 deletions src/apps/escapist-marginalia/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
},
"type": "module",
"dependencies": {
"chaos-game": "workspace:*",
"types": "workspace:*",
"ui": "workspace:*",
"utils": "workspace:*",
"quadtree": "workspace:*",
"@ericrovell/radix": "^1.1.0",
"@ericrovell/vector": "^0.15.0",
"svelte-intl-precompile": "^0.12.3",
Expand Down
6 changes: 0 additions & 6 deletions src/apps/escapist-marginalia/src/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,3 @@ declare module "$locales/*.json" {
const value: DeepDictionary;
export default value;
}

declare namespace App {
interface Session {
userLanguage?: string;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { SketchCanvas } from "@components/sketch";
import { sketch, options as defaultOptions, type Options } from "@content/sketch/chaos-game/index";
import { SketchCanvas } from "$lib/components/sketch";
import { sketch, DEFAULT_OPTIONS, type Options } from "@content/sketch/chaos-game";
import styles from "./chaos-game.module.css";

export let height = 450;
Expand All @@ -19,7 +19,7 @@
{width}
{height}
options={{
...defaultOptions,
...DEFAULT_OPTIONS,
...options
}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default as ChaosGame } from "./ChaosGame.svelte";
export { default as ChaosGame } from "./chaos-game.svelte";
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,15 @@
"slug": "the-chaos-game",
"title": "The Chaos Game: The randomness against determinism",
"translation": {
lang: "русский",
locale: "ru",
slug: "игра-хаоса"
}
}
---

<script>
import { setContext } from "svelte";
import { ChaosGame } from "./components/chaos-game";
import * as Interactive from "./interactive";
import t from "./translations/en.json";

setContext("t", t);
</script>

Fractals - one of the most interesting and mind-breaking mathematical objects. Fractals are self-similar patters. In other words, the part of a fractal looks exactly or partially the same as whole. It may seem that randomness and fractals cannot have anything in common, the rich structure looks deterministic.
Expand All @@ -48,10 +44,7 @@ Let's look at basic the rules, using the example of a triangle:

Thus, the inner area of the triangle is successively filled with points in a chaotic manner. The first thing comes to mind - all these points should fill the area uniformly. Let’s review the rules by example using the interactive section below and get the result:

<Interactive.ChaosGameRulesDemo
origin="{{ y: 50 }}"
t="{t["game-rules-demo"]}"
/>
<Interactive.ChaosGameRules origin="{{ y: 50 }}" />

It is striking that some areas of the triangle cannot be reached in later steps, no matter how many iterations would be done. These “empty” areas form a fractal pattern. The result is a fractal, the so called [Sierpinski triangle][sierpinski-triangle] that was described by the Polish mathematician Waclaw Sierpinski in 1915:

Expand Down Expand Up @@ -114,7 +107,7 @@ There are two outstanding cases: the triangle and the “boring” square. Now w

Up till this moment fractals looked quite “regularly”. The interesting part begins should we intervene into the process of random. Polygon vertices will be chosen randomly as before, but there will be some process moderation: we define some set of restrictions of how the next vertex can or cannot be chosen. Let’s use the “boring” square as the example:

<Interactive.SquareRestrictionsDemo />
<Interactive.SquareRestrictions />

The results are amazing. The “boring” case is not “boring” anymore! We can formulate such restriction rules, quite a lot of them:

Expand All @@ -135,11 +128,11 @@ We won’t count the empty set, we have to move somewhere. For example, there ar

As we can see, each new side double the number of combinations. You can review all the possibilities for some polygons below, just choose the polygon and explore a vast number of new fractals:

<Interactive.ChaosRestrictionSubsetsDemo n="{4}" />
<Interactive.RestrictionSubsets n="{4}" />

In fact, it is not over. There is one more parameter that slipped away. The restrictions do not depend on vertices only, we should restrict it relatively to some choice in the past! This is what makes some restriction rule quite more sophisticated. Let's see what can we get, restricting the same “boring” case as { 1 } for the last choice and { 3 } for penultimate:

<Interactive.ChaosGameRandomRestriction t="{t["random-restrictions"]}" />
<Interactive.RandomRestriction />

With the penultimate rules (we are not restricted here, the restrictions can go deep into the past choices), the number of combinations expands much more: each new restriction multiplies the number of previously possible number of choices for each vertex:

Expand All @@ -153,13 +146,13 @@ Now it time to generalize another rule: the step. Up till now each point moved h

Let's experiment and see, how the step factor affects the result:

<Interactive.ChaosGameStepsDemo />
<Interactive.ChaosGameSteps />

Changing the coefficient we can see how scales up “the figure” looking like polygonal flower with the same number of petals as the number of polygon sides. At some point all these “petals” intersects and mixes up. The coefficient value to get the “flower” depends on the polygon as *r = 3 / (n + 3)*, where n - is the number of sides. This way we can set up more natural step for each Chaos Game depending on the polygon and… yeah, again, “boring” square won’t be boring anymore.

Coefficient is quite practical way to describe the step value, and still, not the only way as it is a relative value. We can freely use absolute value, in other words, move in any direction to any desired distance.

<Interactive.ChaosGameStepsDemo factor={false} />
<Interactive.ChaosGameSteps factor={false} />

## Summing up the adventure

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,15 @@
"slug": "игра-хаоса",
"title": "Игра Хаоса: случайность против детерменизма",
"translation": {
lang: "english",
locale: "en",
slug: "the-chaos-game"
}
}
---

<script>
import { setContext } from "svelte";
import { ChaosGame } from "./components/chaos-game";
import * as Interactive from "./interactive";
import t from "./translations/ru.json";

setContext("t", t);
</script>

Фракталы — одни из самых интересных, поражающих воображение математических объектов. Фракталы обладают свойством самоподобия, иными словами, они в точности или приближённо совпадает с частью самого себя. Может показаться, что случайность и фракталы попросту не могут иметь ничего общего, ведь фракталы — одни из самых детерменистичных объектов, которые только можно себе представить. В этой статье мы познакомимся со способам создавать фрактальные узоры, используя случайность и хаос.
Expand All @@ -48,7 +44,7 @@

Таким образом, внутренняя область многоугольника последовательно заполняется точками хаотичным образом. Может показаться, что в этом алгоритме нет чего-либо примечательного и со временем точки покроют всю доступную область. Иллюстративно ознакомиться с работой алгоритма и взглянуть на результат можно на интерактивной площадке ниже.

<Interactive.ChaosGameRulesDemo origin="{{ y: 50 }}" />
<Interactive.ChaosGameRules origin="{{ y: 50 }}" />

Перед нами предстаёт удивительная картина: некоторые области треугольника так и останутся незакрашенными, несмотря на количество итераций. Результатом окажется фрактал, известный как [«Треугольник Серпинского»][sierpinski-triangle], впервые описанного польским математиком Вацлавом Серпинским в 1915 году:

Expand Down Expand Up @@ -113,7 +109,7 @@

До сих пор фракталы выглядели довольно привычно, если так можно выразиться. Самое интересное начинается, когда мы решим "вмешаться" в процесс "случайности" выбора. Вершины многоугольника всё также будут избираться случайным образом, но с некоторым вмешательством - включением некого свода правил. Рассмотрим это на примере "скучного" четырёхугольника:

<Interactive.SquareRestrictionsDemo />
<Interactive.SquareRestrictions />

Результаты поражают. Тот самый единственный «скучный» случай перестал быть скучным. Стоило лишь немного вмешаться в «случайность», и подобных правил может быть, как может показаться, сформулировано немыслимое количество:

Expand All @@ -136,11 +132,11 @@

В итоге, количество возможных комбинаций удваивается с каждой новой стороной многоугольника. Попробовать рассмотреть все доступные комбинации для типичных многоугольников можно на интерактивной площадке ниже.

<Interactive.ChaosRestrictionSubsetsDemo n="{4}" />
<Interactive.RestrictionSubsets n="{4}" />

На самом деле, этим дело не ограничивается. Наиболее изощренные и интересные формулировки возможно описать лишь множеством ограничений. Это и логично, ведь мы упускаем из виду ещё один параметр — относительно какой уже выбранной вершины мы создаём ограничения. Например, вот что получится при запрете выбора следующей вершины на расстоянии 1 от предыдущей и 3 от предпредыдущей:

<Interactive.ChaosGameRandomRestriction />
<Interactive.RandomRestriction />

С учётом предпредыдущей выбранной вершины для формулировки ограничений (не стоит останавливаться, можно уходить в прошлое ещё «глубже»), количество новых фракталов становится ещё больше: если при ограничении одной вершины количество возможностей 2^n — 1, то после учёта предпредыдущей — все (2^n — 1) * n для каждой их возможных вершин. Если для треугольника это теперь существует 343 комбинации (было всего лишь 7), то для восьмиугольника целых 17 878 103 347 812 890 625!

Expand All @@ -150,13 +146,13 @@

Попробуем поэкспериментировать, как же влияет фактор шага на результат:

<Interactive.ChaosGameStepsDemo />
<Interactive.ChaosGameSteps />

Изменяя коэффициент, можно увидеть, как масштабируется привычный рисунок. Самое важное, чему стоит уделить внимание — при определённой величине шага при отдалении «плотностей точек» друг от друга, можно получить непересекающиеся области. Величина коэффициент при этом будет зависеть от количества сторон многоугольника. В общем случае *r = 3 / (n + 3)*, где n — количество сторон многоугольника. С таким коэффициентом даже обделённый квадрат перестаёт быть скучным и демонстрирует интересный паттерн.

Коэффициент удобен для описания параметра, однако он описывает *относительную* величину шага. Не стоит себя ограничивать, для величины шага можно смело использовать и *абсолютные* значения, другими словами, двигаясь в любом направлении на любое заданное расстояние.

<Interactive.ChaosGameStepsDemo factor={false} />
<Interactive.ChaosGameSteps factor={false} />

## Подводя итоги

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<script lang="ts">
import { getContext } from "svelte";
import { Button, Switch } from "@components";
import { Chaos, createPolygon } from "@content/sketch/chaos-game/index";
import type { Coords, Move, PolygonOrigin } from "@content/sketch/chaos-game/lib/chaos.types";
import styles from "./chaos-game-rules-demo.module.css";
import { Chaos, createPolygon } from "chaos-game";
import type { Coords, Move, PolygonOrigin } from "chaos-game";
import { Button, InputSwitch } from "ui";

import type { Translation } from "../../translations/types";
import styles from "./chaos-game-rules.module.css";

export let height = 350;
export let limit = 3000;
Expand All @@ -16,7 +18,7 @@
export let width = 350;
export let step = { value: 0.5, factor: true };

const t = getContext<Record<string, string>>("t")["game-rules-demo"];
const t = getContext<Translation>("t");

const poly = createPolygon(polygon, scale / 2, origin);
const chaos = new Chaos(poly, { step });
Expand Down Expand Up @@ -55,11 +57,11 @@
Simplistic vector based "Chaos Game" for rules demonstration purposes.
-->
<section class="wide interactive">
<h3>{t["title"]}</h3>
<h3>{t.TITLE_CHAOS_GAME_RULES}</h3>
<article class="{styles.root}">
<aside class="{styles.steps}">
<span>
{t["step-count"]}: <output>{points.length}</output>
{t.STEP_COUNT}: <output>{points.length}</output>
</span>
</aside>
<section class="{styles.polygon}">
Expand Down Expand Up @@ -108,22 +110,22 @@
</section>
<form on:submit|preventDefault class="{styles.form}">
<fieldset class="{styles["controls-render"]}">
<Switch on:change={handleLinesVisibility} checked={showLines}>
{t["show-paths"]}
</Switch>
<Switch on:change={handlePointsVisibility} checked={showPoints}>
{t["show-points"]}
</Switch>
<InputSwitch on:change={handleLinesVisibility} checked={showLines}>
{t.SHOW_PATHS}
</InputSwitch>
<InputSwitch on:change={handlePointsVisibility} checked={showPoints}>
{t.SHOW_POINTS}
</InputSwitch>
</fieldset>
<fieldset class="{styles["controls-actions"]}">
<Button on:click={() => handleNextMove()} disabled={points.length >= limit}>
{t["make-move"]}
{t.MAKE_MOVE}
</Button>
<Button on:click={() => handleNextMove(100)} disabled={points.length >= limit}>
{t["make-move-100"]}
{t.MAKE_MOVE_100}
</Button>
<Button on:click={handleReset} disabled={points.length === 0}>
{t["reset"]}
{t.RESET}
</Button>
</fieldset>
</form>
Expand Down
Loading