2023-06-30

This commit is contained in:
Gennadiy 2023-12-17 07:55:25 +03:00
parent bf9d29c609
commit 09b0d8c349
49 changed files with 4111 additions and 0 deletions

2
.gitattributes vendored
View file

@ -0,0 +1,2 @@
jekyll_site/ru/** linguist-language=JavaScript
jekyll_site/en/** linguist-language=JavaScript

3
.gitignore vendored
View file

@ -1,2 +1,5 @@
.idea .idea
*.iml *.iml
*.zip
_site*
.repo_*.sh

74
DIRECTORY-TREE.md Normal file
View file

@ -0,0 +1,74 @@
## Дерево каталогов
<pre>
.
├─ <a href='jekyll_site'>jekyll_site</a>
│ ├─ <a href='jekyll_site/_includes'>_includes</a>
│ │ ├─ <a href='jekyll_site/_includes/classes-point-cube-en.md'>classes-point-cube-en.md</a>
│ │ ├─ <a href='jekyll_site/_includes/classes-point-cube-ru.md'>classes-point-cube-ru.md</a>
│ │ ├─ <a href='jekyll_site/_includes/counters_body.html'>counters_body.html</a>
│ │ ├─ <a href='jekyll_site/_includes/counters_head.html'>counters_head.html</a>
│ │ ├─ <a href='jekyll_site/_includes/volumetric-tetris-en.html'>volumetric-tetris-en.html</a>
│ │ └─ <a href='jekyll_site/_includes/volumetric-tetris-ru.html'>volumetric-tetris-ru.html</a>
│ ├─ <a href='jekyll_site/css'>css</a>
│ │ └─ <a href='jekyll_site/css/pomodoro1.css'>pomodoro1.css</a>
│ ├─ <a href='jekyll_site/en'>en</a>
│ │ ├─ <a href='jekyll_site/en/2023'>2023</a>
│ │ │ └─ <a href='jekyll_site/en/2023/01'>01</a>
│ │ │ ├─ <a href='jekyll_site/en/2023/01/06'>06</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/01/06/spinning-square-on-plane.md'>spinning-square-on-plane.md</a>
│ │ │ ├─ <a href='jekyll_site/en/2023/01/11'>11</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/01/11/spinning-cube-in-space.md'>spinning-cube-in-space.md</a>
│ │ │ ├─ <a href='jekyll_site/en/2023/01/16'>16</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/01/16/spinning-spatial-cross.md'>spinning-spatial-cross.md</a>
│ │ │ └─ <a href='jekyll_site/en/2023/01/22'>22</a>
│ │ │ └─ <a href='jekyll_site/en/2023/01/22/volumetric-tetris.md'>volumetric-tetris.md</a>
│ │ └─ <a href='jekyll_site/en/index.md'>index.md</a>
│ ├─ <a href='jekyll_site/img'>img</a>
│ │ ├─ <a href='jekyll_site/img/central-projection.svg'>central-projection.svg</a>
│ │ ├─ <a href='jekyll_site/img/column-vector2d.svg'>column-vector2d.svg</a>
│ │ ├─ <a href='jekyll_site/img/column-vector3dx.svg'>column-vector3dx.svg</a>
│ │ ├─ <a href='jekyll_site/img/column-vector3dy.svg'>column-vector3dy.svg</a>
│ │ ├─ <a href='jekyll_site/img/column-vector3dz.svg'>column-vector3dz.svg</a>
│ │ ├─ <a href='jekyll_site/img/euclidean-distance.svg'>euclidean-distance.svg</a>
│ │ ├─ <a href='jekyll_site/img/linear-equation.svg'>linear-equation.svg</a>
│ │ └─ <a href='jekyll_site/img/oblique-projection.svg'>oblique-projection.svg</a>
│ ├─ <a href='jekyll_site/js'>js</a>
│ │ ├─ <a href='jekyll_site/js/classes-point-cube.js'>classes-point-cube.js</a>
│ │ ├─ <a href='jekyll_site/js/spinning-cube.js'>spinning-cube.js</a>
│ │ ├─ <a href='jekyll_site/js/spinning-cube2.js'>spinning-cube2.js</a>
│ │ ├─ <a href='jekyll_site/js/spinning-spatial-cross.js'>spinning-spatial-cross.js</a>
│ │ ├─ <a href='jekyll_site/js/spinning-spatial-cross2.js'>spinning-spatial-cross2.js</a>
│ │ ├─ <a href='jekyll_site/js/spinning-square.js'>spinning-square.js</a>
│ │ ├─ <a href='jekyll_site/js/spinning-square2.js'>spinning-square2.js</a>
│ │ ├─ <a href='jekyll_site/js/tetris-controller.js'>tetris-controller.js</a>
│ │ ├─ <a href='jekyll_site/js/tetris-figures.js'>tetris-figures.js</a>
│ │ ├─ <a href='jekyll_site/js/tetris-model.js'>tetris-model.js</a>
│ │ └─ <a href='jekyll_site/js/tetris-view.js'>tetris-view.js</a>
│ ├─ <a href='jekyll_site/ru'>ru</a>
│ │ ├─ <a href='jekyll_site/ru/2023'>2023</a>
│ │ │ └─ <a href='jekyll_site/ru/2023/01'>01</a>
│ │ │ ├─ <a href='jekyll_site/ru/2023/01/05'>05</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/01/05/spinning-square-on-plane.md'>spinning-square-on-plane.md</a>
│ │ │ ├─ <a href='jekyll_site/ru/2023/01/10'>10</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/01/10/spinning-cube-in-space.md'>spinning-cube-in-space.md</a>
│ │ │ ├─ <a href='jekyll_site/ru/2023/01/15'>15</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/01/15/spinning-spatial-cross.md'>spinning-spatial-cross.md</a>
│ │ │ └─ <a href='jekyll_site/ru/2023/01/21'>21</a>
│ │ │ └─ <a href='jekyll_site/ru/2023/01/21/volumetric-tetris.md'>volumetric-tetris.md</a>
│ │ └─ <a href='jekyll_site/ru/index.md'>index.md</a>
│ ├─ <a href='jekyll_site/Gemfile_color'>Gemfile_color</a>
│ ├─ <a href='jekyll_site/Gemfile_older'>Gemfile_older</a>
│ ├─ <a href='jekyll_site/_config_color.yml'>_config_color.yml</a>
│ ├─ <a href='jekyll_site/_config_older.yml'>_config_older.yml</a>
│ └─ <a href='jekyll_site/robots.txt'>robots.txt</a>
├─ <a href='CONTRIBUTING.md'>CONTRIBUTING.md</a>
├─ <a href='DIRECTORY-TREE.md'>DIRECTORY-TREE.md</a>
├─ <a href='LICENSE.md'>LICENSE.md</a>
├─ <a href='OPEN_LICENSE.txt'>OPEN_LICENSE.txt</a>
├─ <a href='README.en.md'>README.en.md</a>
├─ <a href='README.md'>README.md</a>
├─ <a href='build.sh'>build.sh</a>
├─ <a href='package.sh'>package.sh</a>
└─ <a href='serve.sh'>serve.sh</a>
</pre>

16
README.en.md Normal file
View file

@ -0,0 +1,16 @@
## Website pages
- [Volumetric tetris](https://pomodoro1.mircloud.ru/en/2023/01/22/volumetric-tetris.html) — 22.01.2023.
- [Spinning spatial cross](https://pomodoro1.mircloud.ru/en/2023/01/16/spinning-spatial-cross.html) — 16.01.2023.
- [Spinning cube in space](https://pomodoro1.mircloud.ru/en/2023/01/11/spinning-cube-in-space.html) — 11.01.2023.
- [Spinning square on plane](https://pomodoro1.mircloud.ru/en/2023/01/06/spinning-square-on-plane.html) — 06.01.2023.
## [Source texts](README.md)
- Series of the static websites [«Pomodori»](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.en.md).
- Used formats — Markdown, Liquid, YAML.
- Build tool — Jekyll with tomato design themes.
- Automation of processes — Bash scripts for command line.
- [build.sh](build.sh) — Building a site in two tomato themes and optimizing the results.
- [serve.sh](serve.sh) — Local deployment to verify the correctness of the build.
- [package.sh](package.sh) — Preparing an archive for subsequent deployment.

16
README.md Normal file
View file

@ -0,0 +1,16 @@
## Страницы вёб-сайта
- [Объёмный тетрис](https://pomodoro1.mircloud.ru/ru/2023/01/21/volumetric-tetris.html) — 21.01.2023.
- [Вращаем пространственный крест](https://pomodoro1.mircloud.ru/ru/2023/01/15/spinning-spatial-cross.html) — 15.01.2023.
- [Вращаем куб в пространстве](https://pomodoro1.mircloud.ru/ru/2023/01/10/spinning-cube-in-space.html) — 10.01.2023.
- [Вращаем квадрат на плоскости](https://pomodoro1.mircloud.ru/ru/2023/01/05/spinning-square-on-plane.html) — 05.01.2023.
## [Исходные тексты](README.en.md)
- Серия статических вёб-сайтов [«Помидоры»](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.md).
- Используемые форматы — Markdown, Liquid, YAML.
- Инструмент сборки — Jekyll с помидорными темами оформления.
- Автоматизация процессов — Bash скрипты для командной строки.
- [build.sh](build.sh) — Сборка сайта в двух помидорных темах и оптимизация результатов.
- [serve.sh](serve.sh) — Локальное развёртывание для проверки корректности сборки.
- [package.sh](package.sh) — Подготовка архива для последующего развёртывания.

56
build.sh Executable file
View file

@ -0,0 +1,56 @@
#!/bin/bash
echo "Сборка сайта в двух помидорных темах и оптимизация результатов."
milliseconds=$(date '+%s%3N')
rm -rf _site
rm -rf _site_older
rm -rf _site_color
echo "Сборка старого помидора."
mkdir -p _site_older
cp -r jekyll_site/_includes _site_older
cp -r jekyll_site/ru _site_older
cp -r jekyll_site/en _site_older
cp -r jekyll_site/ru/index.md _site_older
cp -r jekyll_site/_config_older.yml _site_older/_config.yml
cp -r jekyll_site/Gemfile_older _site_older/Gemfile
cd _site_older || exit
jekyll build
cp -r _site ..
cd ..
echo "Сборка цветного помидора."
mkdir -p _site_color
cp -r jekyll_site/_includes _site_color
cp -r jekyll_site/ru _site_color
cp -r jekyll_site/en _site_color
cp -r jekyll_site/ru/index.md _site_color
cp -r jekyll_site/_config_color.yml _site_color/_config.yml
cp -r jekyll_site/Gemfile_color _site_color/Gemfile
cd _site_color || exit
jekyll build
cp -r _site ../_site/color
cd ..
echo "Копирование без сборки."
cp -r jekyll_site/css _site
cp -r jekyll_site/img _site
cp -r jekyll_site/js _site
cp -r jekyll_site/robots.txt _site
echo "Оптимизация собранного контента."
cd _site || exit
cp -r assets/* .
rm -r assets
rm -r color/assets/favicon.ico
cp -r color/assets/* .
rm -r color/assets
rm -r color/404.html
find . -type f -name '*.html' | sort -r | while read -r file; do
sed -i 's/layout-padding=""/layout-padding/g' "$file"
sed -i 's/ class="language-plaintext highlighter-rouge"//g' "$file"
sed -i 's/ class="language-java highlighter-rouge"//g' "$file"
sed -i 's/ class="language-html highlighter-rouge"//g' "$file"
sed -i 's/ class="language-js highlighter-rouge"//g' "$file"
sed -i 's/<div><div class="highlight"><pre class="highlight">/<div class="highlight"><pre class="highlight">/g' "$file"
sed -i 's/<\/code><\/pre><\/div><\/div>/<\/code><\/pre><\/div>/g' "$file"
sed -i 's/<hr \/>/<hr>/g' "$file"
sed -i -r 's/<input(.+) \/>/<input\1>/g' "$file"
sed -i -r 's/<img(.+) \/>/<img\1>/g' "$file"
done
echo "Время выполнения сборки: $(("$(date '+%s%3N')" - "$milliseconds")) мс."

View file

@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "jekyll"
gem "color-tomato-theme"

View file

@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "jekyll"
gem "older-tomato-theme"

View file

@ -0,0 +1,20 @@
# site parameters
name: "Код с комментариями"
name_translated: "Code with comments"
url: "https://pomodoro1.mircloud.ru"
baseurl: "/color"
homepage_url: "https://git.org.ru/pomodoro/1"
homepage_name: "GIT.ORG.RU"
older_tomato_baseurl: ""
timezone: "Europe/Moscow"
author: "Головин Г.Г."
author_translated: "Golovin G.G."
translation_caption: "translation from Russian"
# build parameters
disable_disk_cache: true
theme: color-tomato-theme
defaults:
- scope:
path: ""
values:
layout: default

View file

@ -0,0 +1,20 @@
# site parameters
name: "Код с комментариями"
name_translated: "Code with comments"
url: "https://pomodoro1.mircloud.ru"
baseurl: ""
homepage_url: "https://git.org.ru/pomodoro/1"
homepage_name: "GIT.ORG.RU"
color_tomato_baseurl: "/color"
timezone: "Europe/Moscow"
author: "Головин Г.Г."
author_translated: "Golovin G.G."
translation_caption: "translation from Russian"
# build parameters
disable_disk_cache: true
theme: older-tomato-theme
defaults:
- scope:
path: ""
values:
layout: default

View file

@ -0,0 +1,148 @@
The Point class of the three-dimensional space contains methods for rotations by an angle and for
obtaining projections onto a plane. When obtaining projections, the distance from the point to the
projection center is calculated. Point also contains a static method to compare two projections
of points.
{% capture collapsed_md %}
```js
class Point {
// point coordinates
constructor(x,y,z) {
this.x=x;
this.y=y;
this.z=z;
}
// rotate this point by an angle (deg) along
// axes (x,y,z) relative to the point (t0)
rotate(deg, t0) {
// functions to obtain sine and cosine of angle in radians
const sin = (deg) => Math.sin((Math.PI/180)*deg);
const cos = (deg) => Math.cos((Math.PI/180)*deg);
// calculate new coordinates of point using the formulas
// of the rotation matrix for three-dimensional space
let x,y,z;
// rotation along 'x' axis
y = t0.y+(this.y-t0.y)*cos(deg.x)-(this.z-t0.z)*sin(deg.x);
z = t0.z+(this.y-t0.y)*sin(deg.x)+(this.z-t0.z)*cos(deg.x);
this.y=y; this.z=z;
// rotation along 'y' axis
x = t0.x+(this.x-t0.x)*cos(deg.y)-(this.z-t0.z)*sin(deg.y);
z = t0.z+(this.x-t0.x)*sin(deg.y)+(this.z-t0.z)*cos(deg.y);
this.x=x; this.z=z;
// rotation along 'z' axis
x = t0.x+(this.x-t0.x)*cos(deg.z)-(this.y-t0.y)*sin(deg.z);
y = t0.y+(this.x-t0.x)*sin(deg.z)+(this.y-t0.y)*cos(deg.z);
this.x=x; this.y=y;
}
// get a projection of (type) from a distance (d)
// onto the plane of the observer screen (tv)
projection(type, tv, d) {
let proj = {};
// obtain a projection using experimental formulas
switch (type) {
case 'parallel': {
proj.x = this.x;
proj.y = this.y+(tv.y-this.z)/4;
break;
}
case 'perspective': {
proj.x = tv.x+d*(this.x-tv.x)/(this.z-tv.z+d);
proj.y = tv.y+d*(this.y-tv.y)/(this.z-tv.z+d);
break;
}
}
// calculate distance to projection center
proj.dist = Math.sqrt((this.x-tv.x)*(this.x-tv.x)
+(this.y-tv.y)*(this.y-tv.y)
+(this.z-tv.z+d)*(this.z-tv.z+d));
return proj;
}
// compare two projections of points (p1,p2),
// coordinates (x,y) should match
static pEquals(p1, p2) {
return Math.abs(p1.x-p2.x)<0.0001
&& Math.abs(p1.y-p2.y)<0.0001;
}
};
```
{% endcapture %}
{%- include collapsed_block.html summary="class Point" content=collapsed_md -%}
The Cube class contains a collection of vertices of the Point class and an array of faces. Each face is an
array of 4 vertices, coming from the same point and going clockwise. The Cube contains methods for rotating
all vertices by an angle and for obtaining projections of all faces onto a plane. When obtaining projections,
the tilt of the face is calculated — this is the remoteness from the projection plane. The cube also contains
two static methods for comparing two face projections: for defining the equidistant faces from the projection
center and adjacent walls between neighboring cubes.
{% capture collapsed_md %}
```js
class Cube {
// left upper near coordinate and size
constructor(x,y,z,size) {
// right lower distant coordinate
let xs=x+size,ys=y+size,zs=z+size;
let v={ // vertices
t000: new Point(x,y,z), // top
t001: new Point(x,y,zs), // top
t010: new Point(x,ys,z), // bottom
t011: new Point(x,ys,zs), // bottom
t100: new Point(xs,y,z), // top
t101: new Point(xs,y,zs), // top
t110: new Point(xs,ys,z), // bottom
t111: new Point(xs,ys,zs)};// bottom
this.vertices=v;
this.faces=[ // faces
[v.t000,v.t100,v.t110,v.t010], // front
[v.t000,v.t010,v.t011,v.t001], // left
[v.t000,v.t001,v.t101,v.t100], // upper
[v.t001,v.t011,v.t111,v.t101], // rear
[v.t100,v.t101,v.t111,v.t110], // right
[v.t010,v.t110,v.t111,v.t011]];// lower
}
// rotate vertices of the cube by an angle (deg)
// along axes (x,y,z) relative to the point (t0)
rotate(deg, t0) {
for (let vertex in this.vertices)
this.vertices[vertex].rotate(deg, t0);
}
// get projections of (type) from a distance (d)
// onto the plane of the observer screen (tv)
projection(type, tv, d) {
let proj = [];
for (let face of this.faces) {
// face projection, array of vertices
let p = [];
// cumulative remoteness of vertices
p.dist = 0;
// bypass the vertices of the face
for (let vertex of face) {
// obtain the projections of the vertices
let proj = vertex.projection(type, tv, d);
// accumulate the remoteness of vertices
p.dist+=proj.dist;
// add to array of vertices
p.push(proj);
}
// calculate face tilt, remoteness from the projection plane
p.clock = ((p[1].x-p[0].x)*(p[2].y-p[0].y)
-(p[1].y-p[0].y)*(p[2].x-p[0].x))<0;
proj.push(p);
}
return proj;
}
// compare two projections of faces (f1,f2), vertices
// should be equidistant from the center of projection
static pEquidistant(f1, f2) {
return Math.abs(f1.dist-f2.dist)<0.0001;
}
// compare two projections of faces (f1,f2), coordinates
// of points along the main diagonal (p0,p2) should match
static pAdjacent(f1, f2) {
return Point.pEquals(f1[0],f2[0])
&& Point.pEquals(f1[2],f2[2]);
}
};
```
{% endcapture %}
{%- include collapsed_block.html summary="class Cube" content=collapsed_md -%}

View file

@ -0,0 +1,146 @@
Класс Точка трёхмерного пространства содержит методы для поворотов на угол и для получения проекций
на плоскость. При получении проекций, вычисляется расстояние от точки до центра проекции. Точка также
содержит статический метод для сравнения двух проекций точек.
{% capture collapsed_md %}
```js
class Point {
// координаты точки
constructor(x,y,z) {
this.x=x;
this.y=y;
this.z=z;
}
// поворачиваем эту точку на угол (deg)
// по осям (x,y,z) относительно точки (t0)
rotate(deg, t0) {
// функции для получения синуса и косинуса угла в радианах
const sin = (deg) => Math.sin((Math.PI/180)*deg);
const cos = (deg) => Math.cos((Math.PI/180)*deg);
// получаем новые координаты точки по формулам
// матрицы поворота для трёхмерного пространства
let x,y,z;
// поворот по оси 'x'
y = t0.y+(this.y-t0.y)*cos(deg.x)-(this.z-t0.z)*sin(deg.x);
z = t0.z+(this.y-t0.y)*sin(deg.x)+(this.z-t0.z)*cos(deg.x);
this.y=y; this.z=z;
// поворот по оси 'y'
x = t0.x+(this.x-t0.x)*cos(deg.y)-(this.z-t0.z)*sin(deg.y);
z = t0.z+(this.x-t0.x)*sin(deg.y)+(this.z-t0.z)*cos(deg.y);
this.x=x; this.z=z;
// поворот по оси 'z'
x = t0.x+(this.x-t0.x)*cos(deg.z)-(this.y-t0.y)*sin(deg.z);
y = t0.y+(this.x-t0.x)*sin(deg.z)+(this.y-t0.y)*cos(deg.z);
this.x=x; this.y=y;
}
// получаем проекцию типа (type) с расстояния (d)
// на плоскость экрана наблюдателя (tv)
projection(type, tv, d) {
let proj = {};
// получаем проекцию по экспериментальным формулам
switch (type) {
case 'parallel': {
proj.x = this.x;
proj.y = this.y+(tv.y-this.z)/4;
break;
}
case 'perspective': {
proj.x = tv.x+d*(this.x-tv.x)/(this.z-tv.z+d);
proj.y = tv.y+d*(this.y-tv.y)/(this.z-tv.z+d);
break;
}
}
// вычисляем расстояние до центра проекции
proj.dist = Math.sqrt((this.x-tv.x)*(this.x-tv.x)
+(this.y-tv.y)*(this.y-tv.y)
+(this.z-tv.z+d)*(this.z-tv.z+d));
return proj;
}
// сравниваем две проекции точек (p1,p2),
// координаты (x,y) должны совпадать
static pEquals(p1, p2) {
return Math.abs(p1.x-p2.x)<0.0001
&& Math.abs(p1.y-p2.y)<0.0001;
}
};
```
{% endcapture %}
{%- include collapsed_block.html summary="class Point" content=collapsed_md -%}
Класс Куб содержит коллекцию вершин класса Точка и массив граней. Каждая грань — это массив из 4 вершин,
выходящих из одной точки и идущих по часовой стрелке. Куб содержит методы для поворота всех вершин на угол
и для получения проекций всех граней на плоскость. При получении проекций, вычисляется наклон грани — это
удалённость от плоскости проекции. Куб также содержит два статических метода для сравнения двух проекций
граней: для определения равноудалённых граней от центра проекции и смежных стенок между соседними кубиками.
{% capture collapsed_md %}
```js
class Cube {
// левая верхняя ближняя координата и размер
constructor(x,y,z,size) {
// правая нижняя дальняя координата
let xs=x+size,ys=y+size,zs=z+size;
let v={ // вершины
t000: new Point(x,y,z), // верх
t001: new Point(x,y,zs), // верх
t010: new Point(x,ys,z), // низ
t011: new Point(x,ys,zs), // низ
t100: new Point(xs,y,z), // верх
t101: new Point(xs,y,zs), // верх
t110: new Point(xs,ys,z), // низ
t111: new Point(xs,ys,zs)};// низ
this.vertices=v;
this.faces=[ // грани
[v.t000,v.t100,v.t110,v.t010], // передняя
[v.t000,v.t010,v.t011,v.t001], // левая
[v.t000,v.t001,v.t101,v.t100], // верхняя
[v.t001,v.t011,v.t111,v.t101], // задняя
[v.t100,v.t101,v.t111,v.t110], // правая
[v.t010,v.t110,v.t111,v.t011]];// нижняя
}
// поворачиваем вершины куба на угол (deg)
// по осям (x,y,z) относительно точки (t0)
rotate(deg, t0) {
for (let vertex in this.vertices)
this.vertices[vertex].rotate(deg, t0);
}
// получаем проекции типа (type) с расстояния (d)
// на плоскость экрана наблюдателя (tv)
projection(type, tv, d) {
let proj = [];
for (let face of this.faces) {
// проекция грани, массив вершин
let p = [];
// кумулятивная удалённость вершин
p.dist = 0;
// обходим вершины грани
for (let vertex of face) {
// получаем проекции вершин
let proj = vertex.projection(type, tv, d);
// накапливаем удалённость вершин
p.dist+=proj.dist;
// добавляем в массив вершин
p.push(proj);
}
// вычисляем наклон грани, удалённость от плоскости проекции
p.clock = ((p[1].x-p[0].x)*(p[2].y-p[0].y)
-(p[1].y-p[0].y)*(p[2].x-p[0].x))<0;
proj.push(p);
}
return proj;
}
// сравниваем две проекции граней (f1,f2), вершины
// должны быть равноудалены от центра проекции
static pEquidistant(f1, f2) {
return Math.abs(f1.dist-f2.dist)<0.0001;
}
// сравниваем две проекции граней (f1,f2), координаты
// точек по главной диагонали (p0,p2) должны совпадать
static pAdjacent(f1, f2) {
return Point.pEquals(f1[0],f2[0])
&& Point.pEquals(f1[2],f2[2]);
}
};
```
{% endcapture %}
{%- include collapsed_block.html summary="class Cube" content=collapsed_md -%}

View file

@ -0,0 +1,2 @@
<noscript><div><img src="https://mc.yandex.ru/watch/85726914" style="position:absolute; left:-9999px;" alt=""></div></noscript>
<!-- /Yandex.Metrika counter -->

View file

@ -0,0 +1,16 @@
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-209134013-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-209134013-1');
</script>
<!-- Yandex.Metrika counter -->
<script>
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();for(var j=0;j<document.scripts.length;j++){if(document.scripts[j].src===r){return;}}
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window,document,"script","https://mc.yandex.ru/metrika/tag.js","ym");
ym(85726914,"init",{clickmap:true,trackLinks:true,accurateTrackBounce:true,webvisor:true});
</script>

View file

@ -0,0 +1,111 @@
<div>
<label for="rowsView">Rows</label>
<input type="number" id="rowsView" name="rowsView" min="10" max="28" value="20" onchange="changeRows(event)" class="disabled-sm">
<label for="columnsView">columns</label>
<input type="number" id="columnsView" name="columnsView" min="10" max="28" value="10" onchange="changeColumns(event)" class="disabled-sm">
<label for="snail">snail</label>
<input type="checkbox" id="snail" name="snail" oninput="changeSnailMode(event)">
<meter id="speedometer" min="0" low="300" high="450" max="520" optimum="200" value="0"></meter>
<b id="statusView"></b>
<input type="button" value="Reload" onclick="reload()">
</div>
<div>
<span>Level: <b id="levelView"></b>, next level: <b id="nextLevelView"></b>, score: <b id="scoreView"></b></span>
</div>
<div style="display: flex; flex-direction: row; align-items: start; flex-wrap: wrap;">
<div style="padding: 0 8px 8px 0;">
<canvas id="container">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
<div style="padding: 0 8px 8px 0;">
<canvas id="next">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
<div style="display: flex; flex-direction: column; align-items: start;">
<form oninput="changeVolume(event)">
<div>
<input type="radio" id="off" name="volume" value="off" checked>
<label for="off"><b>Flat image</b></label>
<div style="margin-left: 28px;">
<span>Transparency of figures:</span>
<div>
<input type="range" id="alpha" name="alpha" min="0" max="100" step="1" value="0"
oninput="oAlpha.value = alpha.valueAsNumber + '%'; changeAlpha(event)">
<label for="alpha">A</label>
<output id="oAlpha" name="oAlpha">0%</output>
</div>
<span>Rotation of the playing field:</span>
<div>
<input type="range" id="rotateX" name="rotateX" min="-90" max="90" value="-1" step="1"
oninput="rotateXo.value = rotateX.valueAsNumber + '°'; rotate('x',event)">
<label for="rotateX">X</label>
<output id="rotateXo" name="rotateXo">-1°</output>
</div>
<div>
<input type="range" id="rotateY" name="rotateY" min="-90" max="90" value="0" step="1"
oninput="rotateYo.value = rotateY.valueAsNumber + '°'; rotate('y',event)">
<label for="rotateY">Y</label>
<output id="rotateYo" name="rotateYo"></output>
</div>
<div>
<input type="range" id="rotateZ" name="rotateZ" min="-90" max="90" value="0" step="1"
oninput="rotateZo.value = rotateZ.valueAsNumber + '°'; rotate('z',event)">
<label for="rotateZ">Z</label>
<output id="rotateZo" name="rotateZo"></output>
</div>
</div>
</div>
<div>
<input type="radio" id="parallel" name="volume" value="parallel">
<label for="parallel"><b>Parallel projection</b></label>
<div style="margin-left: 28px;">
<span>Vertical adjustment:</span>
<div>
<input type="range" id="tv1Y" name="tv1Y" min="0" max="100" value="64" step="1"
oninput="tv1Yo.value = tv1Y.valueAsNumber; changeTv1(event)">
<label for="tv1Y">Y</label>
<output id="tv1Yo" name="tv1Yo">64</output>
</div>
</div>
</div>
<div>
<input type="radio" id="perspective" name="volume" value="perspective">
<label for="perspective"><b>Perspective projection</b></label>
<div style="margin-left: 28px;">
<span>Center onto observer screen:</span>
<div>
<input type="range" id="tv2X" name="tv2X" min="0" max="300" value="150" step="1"
oninput="tv2Xo.value = tv2X.valueAsNumber; changeTv2('x',event)">
<label for="tv2X">X</label>
<output id="tv2Xo" name="tv2Xo">150</output>
</div>
<div>
<input type="range" id="tv2Y" name="tv2Y" min="0" max="600" value="300" step="1"
oninput="tv2Yo.value = tv2Y.valueAsNumber; changeTv2('y',event)">
<label for="tv2Y">Y</label>
<output id="tv2Yo" name="tv2Yo">300</output>
</div>
<div>
<input type="range" id="tv2Z" name="tv2Z" min="0" max="150" value="64" step="1"
oninput="tv2Zo.value = tv2Z.valueAsNumber; changeTv2('z',event)">
<label for="tv2Z">Z</label>
<output id="tv2Zo" name="tv2Zo">64</output>
</div>
<span>Remoteness of projection center:</span>
<div>
<input type="range" id="dist" name="dist" min="200" max="800" value="640" step="10"
oninput="oDist.value = dist.valueAsNumber; changeDistance2(event);">
<label for="dist">Z</label>
<output id="oDist" name="oDist">640</output>
</div>
<label for="center">Show the central point:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div>
</div>
</form>
</div>
</div>

View file

@ -0,0 +1,111 @@
<div>
<label for="rowsView">Строки</label>
<input type="number" id="rowsView" name="rowsView" min="10" max="28" value="20" onchange="changeRows(event)" class="disabled-sm">
<label for="columnsView">колонки</label>
<input type="number" id="columnsView" name="columnsView" min="10" max="28" value="10" onchange="changeColumns(event)" class="disabled-sm">
<label for="snail">улитка</label>
<input type="checkbox" id="snail" name="snail" oninput="changeSnailMode(event)">
<meter id="speedometer" min="0" low="300" high="450" max="520" optimum="200" value="0"></meter>
<b id="statusView"></b>
<input type="button" value="Обновить" onclick="reload()">
</div>
<div>
<span>Уровень: <b id="levelView"></b>, следующий уровень: <b id="nextLevelView"></b>, счёт: <b id="scoreView"></b></span>
</div>
<div style="display: flex; flex-direction: row; align-items: start; flex-wrap: wrap;">
<div style="padding: 0 8px 8px 0;">
<canvas id="container">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
<div style="padding: 0 8px 8px 0;">
<canvas id="next">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
<div style="display: flex; flex-direction: column; align-items: start;">
<form oninput="changeVolume(event)">
<div>
<input type="radio" id="off" name="volume" value="off" checked>
<label for="off"><b>Плоское изображение</b></label>
<div style="margin-left: 28px;">
<span>Прозрачность фигур:</span>
<div>
<input type="range" id="alpha" name="alpha" min="0" max="100" step="1" value="0"
oninput="oAlpha.value = alpha.valueAsNumber + '%'; changeAlpha(event)">
<label for="alpha">A</label>
<output id="oAlpha" name="oAlpha">0%</output>
</div>
<span>Поворот игрового поля:</span>
<div>
<input type="range" id="rotateX" name="rotateX" min="-90" max="90" value="-1" step="1"
oninput="rotateXo.value = rotateX.valueAsNumber + '°'; rotate('x',event)">
<label for="rotateX">X</label>
<output id="rotateXo" name="rotateXo">-1°</output>
</div>
<div>
<input type="range" id="rotateY" name="rotateY" min="-90" max="90" value="0" step="1"
oninput="rotateYo.value = rotateY.valueAsNumber + '°'; rotate('y',event)">
<label for="rotateY">Y</label>
<output id="rotateYo" name="rotateYo"></output>
</div>
<div>
<input type="range" id="rotateZ" name="rotateZ" min="-90" max="90" value="0" step="1"
oninput="rotateZo.value = rotateZ.valueAsNumber + '°'; rotate('z',event)">
<label for="rotateZ">Z</label>
<output id="rotateZo" name="rotateZo"></output>
</div>
</div>
</div>
<div>
<input type="radio" id="parallel" name="volume" value="parallel">
<label for="parallel"><b>Параллельная проекция</b></label>
<div style="margin-left: 28px;">
<span>Вертикальная корректировка:</span>
<div>
<input type="range" id="tv1Y" name="tv1Y" min="0" max="100" value="64" step="1"
oninput="tv1Yo.value = tv1Y.valueAsNumber; changeTv1(event)">
<label for="tv1Y">Y</label>
<output id="tv1Yo" name="tv1Yo">64</output>
</div>
</div>
</div>
<div>
<input type="radio" id="perspective" name="volume" value="perspective">
<label for="perspective"><b>Перспективная проекция</b></label>
<div style="margin-left: 28px;">
<span>Центр на экране наблюдателя:</span>
<div>
<input type="range" id="tv2X" name="tv2X" min="0" max="300" value="150" step="1"
oninput="tv2Xo.value = tv2X.valueAsNumber; changeTv2('x',event)">
<label for="tv2X">X</label>
<output id="tv2Xo" name="tv2Xo">150</output>
</div>
<div>
<input type="range" id="tv2Y" name="tv2Y" min="0" max="600" value="300" step="1"
oninput="tv2Yo.value = tv2Y.valueAsNumber; changeTv2('y',event)">
<label for="tv2Y">Y</label>
<output id="tv2Yo" name="tv2Yo">300</output>
</div>
<div>
<input type="range" id="tv2Z" name="tv2Z" min="0" max="150" value="64" step="1"
oninput="tv2Zo.value = tv2Z.valueAsNumber; changeTv2('z',event)">
<label for="tv2Z">Z</label>
<output id="tv2Zo" name="tv2Zo">64</output>
</div>
<span>Удалённость центра проекции:</span>
<div>
<input type="range" id="dist" name="dist" min="200" max="800" value="640" step="10"
oninput="oDist.value = dist.valueAsNumber; changeDistance2(event);">
<label for="dist">Z</label>
<output id="oDist" name="oDist">640</output>
</div>
<label for="center">Показать центральную точку:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div>
</div>
</form>
</div>
</div>

View file

@ -0,0 +1,34 @@
input {
accent-color: #888;
font-size: 100%;
}
input[type="number"] {
border: 1px solid #888;
border-radius: 4px;
max-width: 50px;
}
input[type="radio"] {
scale: 140%;
}
input[type="checkbox"] {
scale: 120%;
}
input:not([disabled]),
input[type="radio"] + label {
cursor: pointer;
}
md-content input {
color: #1b5e20;
}
@media (max-width: 949px) {
.disabled-sm {
pointer-events: none;
color: #888;
}
}

View file

@ -0,0 +1,161 @@
---
title: Spinning square on plane
description: Let's write an algorithm in JavaScript to rotate a square by an angle around its center, repeat the high school program. We will use the Math class for...
sections: [Linear algebra,Rotation matrix]
tags: [javascript,canvas,geometry,graphics,image,picture,square]
scripts: [/js/spinning-square.js,/js/spinning-square2.js]
canonical_url: /en/2023/01/06/spinning-square-on-plane.html
url_translated: /ru/2023/01/05/spinning-square-on-plane.html
title_translated: Вращаем квадрат на плоскости
date: 2023.01.06
lang: en
---
Let's write an algorithm in JavaScript to rotate a square by an angle around its center, repeat the high
school program. We will use the `Math` class for calculations, and Canvas for displaying the results.
Development of thought, volumetric model: [Spinning cube in space]({{ '/en/2023/01/11/spinning-cube-in-space.html' | relative_url }}).
### Point rotation on plane {#point-rotation-on-plane}
We calculate the coordinates of the new point using the formulas of the rotation matrix for
two-dimensional space. We rotate the point `t` relative to the point `t0` we get the point `t'`.
{% include image_svg.html src="/img/column-vector2d.svg" style="width: 246.793pt; height: 37.2836pt;"
alt="&x'=x_0+(x-x_0)cos\varphi-(y-y_0)sin\varphi,&\\&y'=y_0+(x-x_0)sin\varphi+(y-y_0)cos\varphi.&\\" %}
### Algorithm description {#algorithm-description}
The origin of the coordinates is in the upper left corner, the coordinate axes are directed to the right and
down. The central point for rotations `t0` is located in the center of the figure. A square is an array of
four points-vertices. We bypass the array of points, rotate each of them by an angle, then link the points
with lines and draw lines on the canvas. We renew the image at a frequency of 20 frames per second.
### Implementation {#implementation}
<div>
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
### HTML {#html1}
```html
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
```
### JavaScript {#javascript1}
```js
'use strict';
let canvas = document.getElementById('canvas');
// original array of points-vertices of square
let square = [{x:50,y:50},{x:50,y:250},{x:250,y:250},{x:250,y:50}];
// figure center, we'll perform a rotation around it
let t0 = {x:150, y:150};
// rotation angle in degrees
let deg = 1;
```
```js
// figure rotation and image update
function repaint() {
// rotate the original array of points by an angle
for (let i = 0; i < square.length; i++)
square[i] = rotateOnDegree(t0, square[i], deg);
// draw the current array of points
drawFigure(canvas, square);
}
```
```js
// rotate the point (t) by an angle (deg) relative to the point (t0)
function rotateOnDegree(t0, t, deg) {
let t_new = {};
// convert angle of rotation from degrees to radians
let rad = (Math.PI / 180) * deg;
// calculate the coordinates of the new point using the formula
t_new.x = t0.x+(t.x-t0.x)*Math.cos(rad)-(t.y-t0.y)*Math.sin(rad);
t_new.y = t0.y+(t.x-t0.x)*Math.sin(rad)+(t.y-t0.y)*Math.cos(rad);
// return new point
return t_new;
}
```
```js
// draw a figure by points from an array
function drawFigure(canvas, arr) {
let context = canvas.getContext('2d');
// clear the entire canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// bypass the array of points and link them with lines
context.beginPath();
for (let i = 0; i < arr.length; i++)
if (i == 0)
context.moveTo(arr[i].x, arr[i].y);
else
context.lineTo(arr[i].x, arr[i].y);
context.closePath();
// draw lines on the canvas
context.lineWidth = 2.2;
context.strokeStyle = '#222';
context.stroke();
}
```
```js
// after loading the page, set the image refresh interval
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
```
## Spinning backwards {#spinning-backwards}
Let's add one more point, which we'll rotate backwards. The point is distant from the center of the
figure by a quarter of the length of the side of the square. let's shift the center of the square to
this point shift the array of its vertices. We will rotate the square itself clockwise, and its
central point counterclockwise. This code works in conjunction with the previous one.
<div>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
### HTML {#html2}
```html
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
```
### JavaScript {#javascript2}
```js
'use strict';
let canvas2 = document.getElementById('canvas2');
// current array of points
let square2 = [];
// spinning point
let t2 = {x:100, y:100};
```
```js
// figure rotation and image update
function repaint2() {
// rotate the point in the opposite direction
t2 = rotateOnDegree(t0, t2, -deg);
// bypass the points of the original array and shift
for (let i = 0; i < square.length; i++) {
// current point
square2[i] = {};
// shifting the point of the original array
square2[i].x = square[i].x - t0.x + t2.x;
square2[i].y = square[i].y - t0.y + t2.y;
}
// draw the current array of points
drawFigure(canvas2, square2);
}
```
```js
// after loading the page, set the image refresh interval
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint2,50));
```

View file

@ -0,0 +1,229 @@
---
title: Spinning cube in space
description: We consider the difference between parallel and perspective projection. Both are widely used in practice for various purposes. In the previous example, we...
sections: [Linear perspective,Rotation matrix,Experimental model]
tags: [javascript,canvas,geometry,graphics,image,picture,square,cube]
scripts: [/js/classes-point-cube.js,/js/spinning-cube.js,/js/spinning-cube2.js]
styles: [/css/pomodoro1.css]
canonical_url: /en/2023/01/11/spinning-cube-in-space.html
url_translated: /ru/2023/01/10/spinning-cube-in-space.html
title_translated: Вращаем куб в пространстве
date: 2023.01.11
lang: en
---
We consider the difference between parallel and perspective projection.
Both are widely used in practice for various purposes. In the previous example, we
[rotated square on plane]({{ '/en/2023/01/06/spinning-square-on-plane.html' | relative_url }})
we pass into three-dimensional space. Now, to display the rotation of a three-dimensional object
on the screen plane, we first need to create a three-dimensional object, rotate it by an angle,
draw a projection from it and display already the projection on the screen.
Complicated model, many cubes: [Spinning spatial cross]({{ '/en/2023/01/16/spinning-spatial-cross.html' | relative_url }}).
<div style="display: flex; flex-direction: row; flex-wrap: wrap;">
<div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Parallel projection</span>
<canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
<div style="display: flex; flex-direction: column;">
<span>Perspective projection</span>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
</div>
*Parallel projection* the projection center is infinitely distant from the plane of the observer screen,
dimensions of the objects look the same.
*Perspective projection* parallel lines converge in the center of the perspective,
objects appear to shrink in the distance.
## Experimental model {#experimental-model}
Cube size 200, canvas size 300, origin of coordinates is in the upper left corner. The center of the figure
is in the middle of the canvas. The `X` axis is directed to the right, the `Y` axis is directed downwards,
the `Z` axis is directed to the distance. The rotation is performed sequentially around all three axes: first
around the `X` axis, then around the `Y` axis and then around the `Z` axis. Model settings can be controlled,
for example, you can switch off redundant rotation around the axes and change the position of the projection
center onto the observer screen.
<div>
<canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
<form>
<div>
<span>Rotation around axes:</span>
<input type="checkbox" id="rotateX" name="rotateX" checked onchange="changeAxis('x',event)">
<label for="rotateX">X</label>
<input type="checkbox" id="rotateY" name="rotateY" checked onchange="changeAxis('y',event)">
<label for="rotateY">Y</label>
<input type="checkbox" id="rotateZ" name="rotateZ" checked onchange="changeAxis('z',event)">
<label for="rotateZ">Z</label>
</div>
<span>Center onto observer screen:</span>
<div>
<input type="range" id="rangeX" name="rangeX" min="0" max="300" value="150" step="1"
oninput="resultX.value = rangeX.valueAsNumber; changeTv('x',event)">
<label for="rangeX">X</label>
<output id="resultX" name="resultX">150</output>
</div>
<div>
<input type="range" id="rangeY" name="rangeY" min="0" max="300" value="150" step="1"
oninput="resultY.value = rangeY.valueAsNumber; changeTv('y',event)">
<label for="rangeY">Y</label>
<output id="resultY" name="resultY">150</output>
</div>
<div>
<input type="range" id="rangeZ" name="rangeZ" min="50" max="200" value="60" step="1"
oninput="resultZ.value = rangeZ.valueAsNumber; changeTv('z',event)">
<label for="rangeZ">Z</label>
<output name="resultZ">60</output>
</div>
<span>Remoteness of projection center:</span>
<div>
<input type="range" id="distance" name="distance" min="220" max="800" value="300" step="10"
oninput="result.value = distance.valueAsNumber; changeDistance(event);">
<label for="distance">Z</label>
<output name="result">300</output>
</div>
<div>
<label for="center">Show the central point:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div>
</form>
## Point rotation in space {#point-rotation-in-space}
We calculate the new coordinates of the point using the formulas of the rotation matrix for
three-dimensional space. We rotate the point `t` relative to the point `t0` we get the point `t'`.
*Rotation along `X` axis.*
{% include image_svg.html src="/img/column-vector3dx.svg" style="width: 242.619pt; height: 59.0768pt;"
alt="&x'=x,&\\&y'=y_0+(y-y_0)cos\varphi-(z-z_0)sin\varphi,&\\&z'=z_0+(y-y_0)sin\varphi+(z-z_0)cos\varphi.&\\" %}
*Rotation along `Y` axis.*
{% include image_svg.html src="/img/column-vector3dy.svg" style="width: 246.251pt; height: 59.0768pt;"
alt="&x'=x_0+(x-x_0)cos\varphi-(z-z_0)sin\varphi,&\\&y'=y,&\\&z'=z_0+(x-x_0)sin\varphi+(z-z_0)cos\varphi.&\\" %}
*Rotation along `Z` axis.*
{% include image_svg.html src="/img/column-vector3dz.svg" style="width: 246.793pt; height: 55.4753pt;"
alt="&x'=x_0+(x-x_0)cos\varphi-(y-y_0)sin\varphi,&\\&y'=y_0+(x-x_0)sin\varphi+(y-y_0)cos\varphi,&\\&z'=z.&\\" %}
## Point projection {#point-projection}
Experimental formulas with the possibility of shifting the projection center `d0` on the observer
screen `tv`. We map the point of space `t` to the plane of the screen we get the point `t'`.
*Parallel projection.*
{% include image_svg.html src="/img/oblique-projection.svg" style="width: 123.97pt; height: 37.2836pt;"
alt="&x'=x,&\\&y'=y+(y_v-z)/4.&\\" %}
*Perspective projection.*
{% include image_svg.html src="/img/central-projection.svg" style="width: 231.924pt; height: 37.2836pt;"
alt="&x'=x_v+d_0\cdot(x-x_v)/(z-z_v+d_0),&\\&y'=y_v+d_0\cdot(y-y_v)/(z-z_v+d_0).&\\" %}
*Distance from the point to the projection center.*
{% include image_svg.html src="/img/euclidean-distance.svg" style="width: 319.911pt; height: 17.9328pt;"
alt="d(t,d_0)=\sqrt{(x-x_v)^2+(y-y_v)^2+(z-z_v+d_0)^2}." %}
## Face sorting {#face-sorting}
When creating a cube, we set the vertices of each face clockwise. When obtaining a projection, we
substitute three consecutive vertices into the equation of a line, to determine the tilt of the
face and its remoteness from the projection plane.
*Equation of the line, that passes through two points.*
{% include image_svg.html src="/img/linear-equation.svg" style="width: 137.171pt; height: 35.3194pt;"
alt="{(x-x_1)\over(y-y_1)}={(x_2-x_1)\over(y_2-y_1)}." %}
## Algorithm description {#algorithm-description}
First, we bypass the vertices of the cube and rotate them by an angle relative to the center point. Then
we bypass the faces of the cube and get projections of the vertices included in them. After that, we sort
the projections of the faces by remoteness. Then we draw projections on the plane we link the points
with lines. We draw with a translucent color first the far faces and atop them the near ones, so that
the far faces can be seen through the near ones.
At each step of displaying the figure, we repeat the sorting of the faces by remoteness, since
with a change in the angle of rotation, the coordinates shift, and the near faces become far.
## Implementation in JavaScript {#implementation-in-javascript}
{% include classes-point-cube-en.md -%}
Create an object and draw two projections on the plane.
```js
'use strict';
// we will draw two pictures at once, there will be
// one object, and there will be many projections
const canvas1 = document.getElementById('canvas1');
const canvas2 = document.getElementById('canvas2');
// create an object
const cube = new Cube(50,50,50,200);
// figure center, we'll perform a rotation around it
const t0 = new Point(150,150,150);
// remoteness of the projection center
const d = 300;
// observer screen position
const tv = new Point(150,150,80);
// rotation angle in degrees
const deg = {x:0,y:1,z:0};
```
```js
// figure rotation and image update
function repaint() {
cube.rotate(deg, t0);
// draw parallel projection
drawFigure(canvas1, cube.projection('parallel', tv));
// draw perspective projection
drawFigure(canvas2, cube.projection('perspective', tv, d));
}
```
```js
// draw a figure by points from an array
function drawFigure(canvas, proj) {
let context = canvas.getContext('2d');
// sort the faces by their tilt
proj.sort((a,b) => b.clock-a.clock);
// clear the entire canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// bypass the array of cube faces
for (let i = 0; i < proj.length; i++) {
// bypass the array of points and link them with lines
context.beginPath();
for (let j = 0; j < proj[i].length; j++) {
if (j == 0) {
context.moveTo(proj[i][j].x, proj[i][j].y);
} else {
context.lineTo(proj[i][j].x, proj[i][j].y);
}
}
context.closePath();
// draw the face of the cube along with the edges
context.lineWidth = 2.2;
context.lineJoin = 'round';
context.fillStyle = '#fff9';
context.strokeStyle = '#222';
context.fill();
context.stroke();
}
}
```
```js
// after loading the page, set the image refresh interval
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
```

View file

@ -0,0 +1,275 @@
---
title: Spinning spatial cross
description: We are writing an algorithm for rotating a three-dimensional figure by an angle around its center along all three axes at once. In the previous example...
sections: [Volumetric figures,Rotation matrix,Experimental model]
tags: [javascript,canvas,geometry,matrix,graphics,image,picture,square,cube]
scripts: [/js/classes-point-cube.js,/js/spinning-spatial-cross.js,/js/spinning-spatial-cross2.js]
styles: [/css/pomodoro1.css]
canonical_url: /en/2023/01/16/spinning-spatial-cross.html
url_translated: /ru/2023/01/15/spinning-spatial-cross.html
title_translated: Вращаем пространственный крест
date: 2023.01.16
lang: en
---
We are writing an algorithm for rotating a three-dimensional figure by an angle
around its center along all three axes at once. In the previous example, we
[rotated cube in space]({{ '/en/2023/01/11/spinning-cube-in-space.html' | relative_url }})
now there are a lot of cubes, the algorithm is almost the same and we use the same formulas.
We draw two variants of the figure: *spatial cross* and *cross-cube* in two types of projections,
consider the difference.
Testing the experimental interface: [Volumetric tetris]({{ '/en/2023/01/22/volumetric-tetris.html' | relative_url }}).
## Spatial cross {#spatial-cross}
<div style="display: flex; flex-direction: row; flex-wrap: wrap;">
<div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Parallel projection</span>
<canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
<div style="display: flex; flex-direction: column;">
<span>Perspective projection</span>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
</div>
## Cross-cube {#cross-cube}
<div style="display: flex; flex-direction: row; flex-wrap: wrap;">
<div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Parallel projection</span>
<canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
<div style="display: flex; flex-direction: column;">
<span>Perspective projection</span>
<canvas id="canvas4" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
</div>
*Parallel projection* all cubes are the same size.
*Perspective projection* the cubes look shrinking in the distance.
## Experimental model {#experimental-model}
Slightly complicated version from the previous example now there are a lot of cubes. In addition to the
previous settings there can be changed: figure variant *spatial cross* or *cross-cube*, face sorting
direction *linear perspective* or *reverse perspective* and transparency of the cube walls.
<div>
<canvas id="canvas5" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p>
</canvas>
</div>
<div>
<form>
<div>
<span>Rotation around axes:</span>
<input type="checkbox" id="rotateX" name="rotateX" checked onchange="changeAxis('x',event)">
<label for="rotateX">X</label>
<input type="checkbox" id="rotateY" name="rotateY" checked onchange="changeAxis('y',event)">
<label for="rotateY">Y</label>
<input type="checkbox" id="rotateZ" name="rotateZ" checked onchange="changeAxis('z',event)">
<label for="rotateZ">Z</label>
</div>
<span>Center onto observer screen:</span>
<div>
<input type="range" id="rangeX" name="rangeX" min="0" max="300" value="150" step="1"
oninput="resultX.value = rangeX.valueAsNumber; changeTv('x',event)">
<label for="rangeX">X</label>
<output id="resultX" name="resultX">150</output>
</div>
<div>
<input type="range" id="rangeY" name="rangeY" min="0" max="300" value="150" step="1"
oninput="resultY.value = rangeY.valueAsNumber; changeTv('y',event)">
<label for="rangeY">Y</label>
<output id="resultY" name="resultY">150</output>
</div>
<div>
<input type="range" id="rangeZ" name="rangeZ" min="50" max="220" value="125" step="1"
oninput="resultZ.value = rangeZ.valueAsNumber; changeTv('z',event)">
<label for="rangeZ">Z</label>
<output name="resultZ">125</output>
</div>
<span>Remoteness of projection center:</span>
<div>
<input type="range" id="distance" name="distance" min="220" max="800" value="300" step="10"
oninput="result.value = distance.valueAsNumber; changeDistance(event);">
<label for="distance">Z</label>
<output name="result">300</output>
</div>
<div>
<label for="center">Show the central point:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div>
<span>Transparency of cubes:</span>
<div>
<input type="range" id="alpha" name="alpha" min="0" max="100" step="1" value="20"
oninput="oAlpha.value = alpha.valueAsNumber + '%'; changeAlpha(event)">
<label for="alpha">A</label>
<output name="oAlpha">20%</output>
</div>
</form>
<span>Variant of the figure:</span>
<form oninput="changeFigure(event)">
<input type="radio" id="first" name="figure" value="first">
<label for="first">Cross</label>
<input type="radio" id="second" name="figure" value="second" checked>
<label for="second">Cube</label>
</form>
<span>Perspective projection:</span>
<form oninput="changeOrder(event)">
<input type="radio" id="linear" name="order" value="linear" checked>
<label for="linear">Linear</label>
<input type="radio" id="reverse" name="order" value="reverse">
<label for="reverse">Reverse</label>
</form>
</div>
## Algorithm description {#algorithm-description}
We prepare a matrix of zeros and ones, where one means a cube in a certain place of the figure. Then we
bypass this matrix and fill in the array of cubes with the corresponding coordinates of the vertices. After
that, we start the rotation along all three axes at once. At each step, we bypass the array of cubes and get
projections of their faces. Then we sort the array of faces by remoteness from the projection center, bypass
this array and throw away the same pairs from it these are the adjacent walls between neighboring cubes
inside the figure. After that we draw cube faces with a translucent color first the distant and then the
near ones, so that the distant faces can be seen through the near ones.
## Implementation in JavaScript {#implementation-in-javascript}
{% include classes-point-cube-en.md -%}
Create objects according to templates and draw their projections on the plane.
```js
'use strict';
// matrices-templates for cubes
const shape1 = [ // spatial cross
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]];
const shape2 = [ // cross-cube
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]],
[[0,0,1,0,0], [0,0,0,0,0], [1,0,0,0,1], [0,0,0,0,0], [0,0,1,0,0]],
[[1,1,1,1,1], [1,0,0,0,1], [1,0,0,0,1], [1,0,0,0,1], [1,1,1,1,1]],
[[0,0,1,0,0], [0,0,0,0,0], [1,0,0,0,1], [0,0,0,0,0], [0,0,1,0,0]],
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]]];
// cube size, number of cubes in a row, indent
const size = 40, row = 5, gap = 50;
// arrays for cubes
const cubes1 = [], cubes2 = [];
// bypass the matrices, fill the arrays with cubes
for (let x=0; x<row; x++)
for (let y=0; y<row; y++)
for (let z=0; z<row; z++) {
if (shape1[x][y][z]==1)
cubes1.push(new Cube(x*size+gap,y*size+gap,z*size+gap,size));
if (shape2[x][y][z]==1)
cubes2.push(new Cube(x*size+gap,y*size+gap,z*size+gap,size));
}
// figure center, we'll perform a rotation around it
const t0 = new Point(150,150,150);
// remoteness of the projection center
const d = 300;
// observer screen position
const tv = new Point(150,150,125);
// rotation angle in degrees
const deg = {x:1,y:1,z:1};
```
```js
// we'll draw two pictures for each figure
const canvas1 = document.getElementById('canvas1');
const canvas2 = document.getElementById('canvas2');
const canvas3 = document.getElementById('canvas3');
const canvas4 = document.getElementById('canvas4');
// image refresh
function repaint() {
// spatial cross
processFigure(cubes1,canvas1,canvas2);
// cross-cube
processFigure(cubes2,canvas3,canvas4);
}
```
```js
// rotate the figure and get projections
function processFigure(cubes,cnv1,cnv2) {
// arrays of projections of faces of cubes
let parallel = [], perspective = [];
// rotate the cubes and get projections
for (let cube of cubes) {
cube.rotate(deg, t0);
parallel = parallel.concat(cube.projection('parallel',tv,d));
perspective = perspective.concat(cube.projection('perspective',tv,d));
}
// we do not draw adjacent walls between neighboring cubes
noAdjacent(parallel);
noAdjacent(perspective);
// sort the faces of different cubes by remoteness and inside one cube by tilt
parallel.sort((a,b)=>Math.abs(b.dist-a.dist)>size ? b.dist-a.dist : b.clock-a.clock);
// sort the faces by remoteness from the projection center
perspective.sort((a,b)=>b.dist-a.dist);
// draw parallel projection
drawFigure(cnv1, parallel);
// draw perspective projection
drawFigure(cnv2, perspective);
}
```
```js
// do not draw adjacent walls between neighboring cubes
function noAdjacent(array) {
// sort the faces by remoteness
array.sort((a,b) => b.dist-a.dist);
// remove the adjacent walls between cubes
for (let i=0, j=1; i<array.length-1; j=++i+1)
while (j<array.length && Cube.pEquidistant(array[i],array[j]))
if (Cube.pAdjacent(array[i],array[j])) {
array.splice(j,1);
array.splice(i,1);
i--; j=array.length;
} else j++;
}
```
```js
// draw a figure by points from an array
function drawFigure(canvas, proj, alpha=0.8) {
const context = canvas.getContext('2d');
// clear the entire canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// bypass the array of cube faces
for (let i = 0; i < proj.length; i++) {
// bypass the array of points and link them with lines
context.beginPath();
for (let j = 0; j < proj[i].length; j++) {
if (j == 0) {
context.moveTo(proj[i][j].x, proj[i][j].y);
} else {
context.lineTo(proj[i][j].x, proj[i][j].y);
}
}
context.closePath();
// draw the face of the cube along with the edges
context.lineWidth = 1.9;
context.lineJoin = 'round';
context.fillStyle = 'rgba(200,230,201,'+alpha+')';
context.strokeStyle = 'rgba(102,187,106,'+(0.2+alpha)+')';
context.fill();
context.stroke();
}
}
```
```js
// after loading the page, set the image refresh interval
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
```

View file

@ -0,0 +1,53 @@
---
title: Volumetric tetris
description: General educational game in the broad meaning of this word. When learning programming languages, it is recommended to write your own version first and then...
sections: [Logical game,Experimental interface]
tags: [javascript,canvas,game,puzzle,geometry,matrix,graphics,square,cube,3d,three-dimensional]
scripts: [/js/classes-point-cube.js,/js/tetris-figures.js,/js/tetris-model.js,/js/tetris-controller.js,/js/tetris-view.js]
styles: [/css/pomodoro1.css]
canonical_url: /en/2023/01/22/volumetric-tetris.html
url_translated: /ru/2023/01/21/volumetric-tetris.html
title_translated: Объёмный тетрис
date: 2023.01.22
lang: en
---
General educational game in the broad meaning of this word. When learning programming languages, it is
recommended to write your own version first and then use it to demonstrate and test other software or
hardware. The three-dimensional interface is written in JavaScript Canvas the logic of the game itself
is two-dimensional.
Description of graphics algorithm: [Spinning cube in space]({{ '/en/2023/01/11/spinning-cube-in-space.html' | relative_url }}).
## Experimental interface {#experimental-interface}
Turned off by default you can just play Tetris. In addition to the flat version, two volumetric variants
are added: *parallel projection* and *perspective projection* parameters for each of them can be changed.
For perspective projection: you can change the position of the observer screen and the remoteness of the
projection source. The observer looks at the center of the image, and the center of the projection is remote
at a distance, comparable to the size of the playing field. For parallel projection: you can change the
vertical position. For both projections: you can rotate the playing field along all three axes. The central
point for rotations is the central lower far point of the field. For all variants of the image: the size
of the cube 32, the size of the square 30 and the indent 2. The origin of coordinates is located at
the upper left point, the axes are directed: `X` to the right, `Y` downwards and `Z` to the distance.
*Usage example:* start the game, collect a certain number of figures on the field, then pause the game, and
switch between the variants of the three-dimensional image, rotate the field with figures, change the settings.
{% include volumetric-tetris-en.html -%}
## Gaming process {#gaming-process}
Controls: keyboard buttons with arrows right, left, up, down and the button `pause`.
Game points are awarded for fully collected rows of the elements of the figures. The number of points scored
depends on the number of rows collected, 10 points for each row if there are 10 cubes in a row, and multiply
increases, if collected at the same time: 2 lines by 3 times, 3 lines by 5 times, 4 lines by 10 times.
Game feature: the collected lines first blink and then disappear, while the gaming process is not suspended
for this time the current figure continues to fall.
Level increases when collecting 10 completed rows, that is 100 points, if there are 10 cubes in a row. At each
new level, the speed of the figures increases and reaches its maximum at level 21. In snail mode, the speed
increases 5 times slower and reaches a maximum at level 104. The current speed is displayed above the playing
field as a `meter` indicator.

48
jekyll_site/en/index.md Normal file
View file

@ -0,0 +1,48 @@
---
title: Code with comments
description: Notes about programming with code snippets and comments. Problem solutions and solution descriptions.
sections: [Problem solutions and solution descriptions]
tags: [javascript,canvas,geometry,matrix,algorithms,implementation,graphics,images,pictures,square,cube]
canonical_url: /en/
url_translated: /ru/
title_translated: Код с комментариями
lang: en
---
{%- assign articles = "" | split: "" %}
{%- assign articles = articles | push: "Volumetric tetris" %}
{%- capture article_brief %}
General educational game in the broad meaning of this word. When learning programming languages, it is
recommended to write your own version first and then use it to demonstrate and test other software or
hardware. The three-dimensional interface is written in JavaScript Canvas the logic of the game itself
is two-dimensional.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Spinning spatial cross" %}
{%- capture article_brief %}
We are writing an algorithm for rotating a three-dimensional figure by an angle around its center along all three
axes at once. In the previous example, we rotated cube in space now there are a lot of cubes, the algorithm is
almost the same and we use the same formulas. We draw two variants of the figure: *spatial cross* and *cross-cube*
in two types of projections, consider the difference.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Spinning cube in space" %}
{%- capture article_brief %}
We consider the difference between parallel and perspective projection. Both are widely used in practice for various
purposes. In the previous example, we rotated square on plane we pass into three-dimensional space. Now, to display
the rotation of a three-dimensional object on the screen plane, we first need to create a three-dimensional object,
rotate it by an angle, draw a projection from it and display already the projection on the screen.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Spinning square on plane" %}
{%- capture article_brief %}
Let's write an algorithm in JavaScript to rotate a square by an angle around its center, repeat the high
school program. We will use the `Math` class for calculations, and Canvas for displaying the results.
The origin of the coordinates is in the upper left corner, the coordinate axes are directed to the right and
down. The central point for rotations `t0` is located in the center of the figure. A square is an array of
four points-vertices. We bypass the array of points, rotate each of them by an angle, then link the points
with lines and draw lines on the canvas. We renew the image at a frequency of 20 frames per second.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- include main_page.html articles = articles -%}

View file

@ -0,0 +1,75 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="231.924pt" height="37.2836pt" viewBox="132.578 103.454 231.924 37.2836">
<defs>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g1-0"/>
<path d="M2.29539 -2.98879C2.29539 -3.33549 2.00847 -3.62242 1.66177 -3.62242S1.02814 -3.33549 1.02814 -2.98879S1.31507 -2.35517 1.66177 -2.35517S2.29539 -2.64209 2.29539 -2.98879Z" id="g1-1"/>
<path d="M3.96115 -2.90112C3.96115 -3.52279 3.60249 -3.52279 3.57061 -3.52279C3.37933 -3.52279 3.15616 -3.31557 3.15616 -3.10834C3.15616 -2.98082 3.21993 -2.92503 3.29166 -2.86127C3.47497 -2.70187 3.58655 -2.4787 3.58655 -2.22366C3.58655 -1.85704 3.06052 -0.143462 2.14396 -0.143462C1.80125 -0.143462 1.52229 -0.326775 1.52229 -0.828892C1.52229 -1.26725 1.76139 -1.89689 1.95268 -2.37509C2.04832 -2.63014 2.07223 -2.6939 2.07223 -2.83736C2.07223 -3.26775 1.72154 -3.51482 1.35492 -3.51482C0.565878 -3.51482 0.239103 -2.39103 0.239103 -2.29539C0.239103 -2.22366 0.294894 -2.19178 0.358655 -2.19178C0.462267 -2.19178 0.470237 -2.2396 0.494147 -2.3193C0.70137 -3.0127 1.04408 -3.29166 1.33101 -3.29166C1.45056 -3.29166 1.52229 -3.21993 1.52229 -3.02864C1.52229 -2.84533 1.45056 -2.66202 1.37086 -2.46276C0.980324 -1.45853 0.948443 -1.19552 0.948443 -0.948443C0.948443 -0.0797011 1.65778 0.0797011 2.11208 0.0797011C3.43512 0.0797011 3.96115 -2.29539 3.96115 -2.90112Z" id="g2-118"/>
<path d="M2.11208 -3.77783C2.15193 -3.88144 2.18381 -3.93724 2.18381 -4.01694C2.18381 -4.27995 1.94471 -4.45529 1.72154 -4.45529C1.40274 -4.45529 1.31507 -4.17634 1.28319 -4.06476L0.270984 -0.629639C0.239103 -0.533998 0.239103 -0.510087 0.239103 -0.502117C0.239103 -0.430386 0.286924 -0.414446 0.366625 -0.390535C0.510087 -0.326775 0.526027 -0.326775 0.541968 -0.326775C0.565878 -0.326775 0.613699 -0.326775 0.669489 -0.462267L2.11208 -3.77783Z" id="g0-48"/>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g5-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g5-41"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g5-43"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g5-61"/>
<path d="M3.89738 -2.54247C3.89738 -3.39527 3.80971 -3.91333 3.5467 -4.42341C3.19601 -5.12478 2.55044 -5.30012 2.11208 -5.30012C1.10785 -5.30012 0.74122 -4.55093 0.629639 -4.32777C0.342715 -3.74595 0.326775 -2.95691 0.326775 -2.54247C0.326775 -2.01644 0.350685 -1.21146 0.73325 -0.573848C1.09988 0.0159402 1.68966 0.167372 2.11208 0.167372C2.49465 0.167372 3.18007 0.0478207 3.57858 -0.74122C3.87347 -1.31507 3.89738 -2.02441 3.89738 -2.54247ZM2.11208 -0.0557908C1.8411 -0.0557908 1.29116 -0.183313 1.12379 -1.02017C1.03611 -1.47447 1.03611 -2.22366 1.03611 -2.63811C1.03611 -3.18804 1.03611 -3.74595 1.12379 -4.18431C1.29116 -4.99726 1.91283 -5.07696 2.11208 -5.07696C2.38306 -5.07696 2.933 -4.94147 3.0924 -4.21619C3.18804 -3.77783 3.18804 -3.18007 3.18804 -2.63811C3.18804 -2.16787 3.18804 -1.45056 3.0924 -1.00423C2.92503 -0.167372 2.37509 -0.0557908 2.11208 -0.0557908Z" id="g4-48"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g3-58"/>
<path d="M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z" id="g3-59"/>
<path d="M5.12877 -8.52403C5.12877 -8.53599 5.2005 -8.71532 5.2005 -8.73923C5.2005 -8.88269 5.08095 -8.96638 4.98531 -8.96638C4.92553 -8.96638 4.81793 -8.96638 4.72229 -8.70336L0.71731 2.54645C0.71731 2.55841 0.645579 2.73773 0.645579 2.76164C0.645579 2.90511 0.765131 2.98879 0.860772 2.98879C0.932503 2.98879 1.0401 2.97684 1.12379 2.72578L5.12877 -8.52403Z" id="g3-61"/>
<path d="M6.01345 -7.99801C6.0254 -8.04583 6.04932 -8.11756 6.04932 -8.17733C6.04932 -8.29689 5.92976 -8.29689 5.90585 -8.29689C5.8939 -8.29689 5.30809 -8.24907 5.24832 -8.23711C5.04508 -8.22516 4.86575 -8.20125 4.65056 -8.18929C4.35168 -8.16538 4.268 -8.15342 4.268 -7.93823C4.268 -7.81868 4.36364 -7.81868 4.53101 -7.81868C5.11681 -7.81868 5.12877 -7.71108 5.12877 -7.59153C5.12877 -7.5198 5.10486 -7.42416 5.0929 -7.38829L4.36364 -4.48319C4.23213 -4.79402 3.90934 -5.27223 3.28767 -5.27223C1.93674 -5.27223 0.478207 -3.52677 0.478207 -1.75741C0.478207 -0.573848 1.17161 0.119552 1.98456 0.119552C2.64209 0.119552 3.20399 -0.394521 3.53873 -0.789041C3.65828 -0.0836862 4.22017 0.119552 4.57883 0.119552S5.22441 -0.0956413 5.4396 -0.526027C5.63088 -0.932503 5.79826 -1.66177 5.79826 -1.70959C5.79826 -1.76936 5.75044 -1.81719 5.6787 -1.81719C5.57111 -1.81719 5.55915 -1.75741 5.51133 -1.57808C5.332 -0.872727 5.10486 -0.119552 4.61469 -0.119552C4.268 -0.119552 4.24408 -0.430386 4.24408 -0.669489C4.24408 -0.71731 4.24408 -0.968369 4.32777 -1.30311L6.01345 -7.99801ZM3.59851 -1.42267C3.53873 -1.21943 3.53873 -1.19552 3.37136 -0.968369C3.10834 -0.633624 2.58232 -0.119552 2.02042 -0.119552C1.53026 -0.119552 1.25529 -0.561893 1.25529 -1.26725C1.25529 -1.92478 1.6259 -3.26376 1.85305 -3.76588C2.25953 -4.60274 2.82142 -5.03313 3.28767 -5.03313C4.07671 -5.03313 4.23213 -4.0528 4.23213 -3.95716C4.23213 -3.94521 4.19626 -3.78979 4.18431 -3.76588L3.59851 -1.42267Z" id="g3-100"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g3-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g3-121"/>
<path d="M1.51831 -0.968369C2.03238 -1.55417 2.45081 -1.92478 3.04857 -2.46276C3.76588 -3.08443 4.07671 -3.38331 4.24408 -3.56264C5.08095 -4.38755 5.49938 -5.08095 5.49938 -5.17659S5.40374 -5.27223 5.37983 -5.27223C5.29614 -5.27223 5.27223 -5.22441 5.21245 -5.14072C4.91357 -4.62665 4.62665 -4.37559 4.31582 -4.37559C4.06476 -4.37559 3.93325 -4.48319 3.7061 -4.77011C3.45504 -5.06899 3.25181 -5.27223 2.90511 -5.27223C2.03238 -5.27223 1.50635 -4.18431 1.50635 -3.93325C1.50635 -3.89738 1.51831 -3.82565 1.6259 -3.82565C1.72154 -3.82565 1.7335 -3.87347 1.76936 -3.95716C1.9726 -4.43537 2.54645 -4.51905 2.7736 -4.51905C3.02466 -4.51905 3.26376 -4.43537 3.51482 -4.32777C3.96912 -4.13649 4.1604 -4.13649 4.27995 -4.13649C4.36364 -4.13649 4.41146 -4.13649 4.47123 -4.14844C4.07671 -3.68219 3.43113 -3.10834 2.89315 -2.61818L1.68568 -1.50635C0.956413 -0.765131 0.514072 -0.0597758 0.514072 0.0239103C0.514072 0.0956413 0.573848 0.119552 0.645579 0.119552S0.729265 0.107597 0.812951 -0.0358655C1.00423 -0.334745 1.3868 -0.777086 1.82914 -0.777086C2.0802 -0.777086 2.19975 -0.6934 2.43885 -0.394521C2.666 -0.131507 2.86924 0.119552 3.25181 0.119552C4.42341 0.119552 5.0929 -1.39875 5.0929 -1.67372C5.0929 -1.72154 5.08095 -1.79328 4.96139 -1.79328C4.86575 -1.79328 4.8538 -1.74545 4.81793 -1.6259C4.55492 -0.920548 3.84956 -0.633624 3.38331 -0.633624C3.13225 -0.633624 2.89315 -0.71731 2.64209 -0.824907C2.16389 -1.01619 2.03238 -1.01619 1.87696 -1.01619C1.75741 -1.01619 1.6259 -1.01619 1.51831 -0.968369Z" id="g3-122"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.245 0 0 1.25 0 0)">
<use x="106.062" xlink:href="#g3-120" y="92.1544"/>
<use x="112.69" xlink:href="#g0-48" y="87.2182"/>
<use x="118.806" xlink:href="#g5-61" y="92.1544"/>
<use x="131.197" xlink:href="#g3-120" y="92.1544"/>
<use x="137.824" xlink:href="#g2-118" y="93.9477"/>
<use x="145.388" xlink:href="#g5-43" y="92.1544"/>
<use x="157.116" xlink:href="#g3-100" y="92.1544"/>
<use x="163.176" xlink:href="#g4-48" y="93.9477"/>
<use x="170.565" xlink:href="#g1-1" y="92.1544"/>
<use x="176.53" xlink:href="#g5-40" y="92.1544"/>
<use x="181.065" xlink:href="#g3-120" y="92.1544"/>
<use x="190.349" xlink:href="#g1-0" y="92.1544"/>
<use x="202.269" xlink:href="#g3-120" y="92.1544"/>
<use x="208.897" xlink:href="#g2-118" y="93.9477"/>
<use x="213.804" xlink:href="#g5-41" y="92.1544"/>
<use x="218.34" xlink:href="#g3-61" y="92.1544"/>
<use x="224.171" xlink:href="#g5-40" y="92.1544"/>
<use x="228.706" xlink:href="#g3-122" y="92.1544"/>
<use x="237.313" xlink:href="#g1-0" y="92.1544"/>
<use x="249.233" xlink:href="#g3-122" y="92.1544"/>
<use x="254.651" xlink:href="#g2-118" y="93.9477"/>
<use x="262.215" xlink:href="#g5-43" y="92.1544"/>
<use x="273.943" xlink:href="#g3-100" y="92.1544"/>
<use x="280.003" xlink:href="#g4-48" y="93.9477"/>
<use x="284.735" xlink:href="#g5-41" y="92.1544"/>
<use x="289.27" xlink:href="#g3-59" y="92.1544"/>
<use x="106.062" xlink:href="#g3-121" y="109.589"/>
<use x="112.178" xlink:href="#g0-48" y="104.653"/>
<use x="118.294" xlink:href="#g5-61" y="109.589"/>
<use x="130.685" xlink:href="#g3-121" y="109.589"/>
<use x="136.371" xlink:href="#g2-118" y="111.382"/>
<use x="143.936" xlink:href="#g5-43" y="109.589"/>
<use x="155.663" xlink:href="#g3-100" y="109.589"/>
<use x="161.723" xlink:href="#g4-48" y="111.382"/>
<use x="169.112" xlink:href="#g1-1" y="109.589"/>
<use x="175.077" xlink:href="#g5-40" y="109.589"/>
<use x="179.612" xlink:href="#g3-121" y="109.589"/>
<use x="188.384" xlink:href="#g1-0" y="109.589"/>
<use x="200.305" xlink:href="#g3-121" y="109.589"/>
<use x="205.991" xlink:href="#g2-118" y="111.382"/>
<use x="210.899" xlink:href="#g5-41" y="109.589"/>
<use x="215.434" xlink:href="#g3-61" y="109.589"/>
<use x="221.265" xlink:href="#g5-40" y="109.589"/>
<use x="225.801" xlink:href="#g3-122" y="109.589"/>
<use x="234.407" xlink:href="#g1-0" y="109.589"/>
<use x="246.328" xlink:href="#g3-122" y="109.589"/>
<use x="251.745" xlink:href="#g2-118" y="111.382"/>
<use x="259.31" xlink:href="#g5-43" y="109.589"/>
<use x="271.037" xlink:href="#g3-100" y="109.589"/>
<use x="277.097" xlink:href="#g4-48" y="111.382"/>
<use x="281.829" xlink:href="#g5-41" y="109.589"/>
<use x="286.365" xlink:href="#g3-58" y="109.589"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,80 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="246.793pt" height="37.2836pt" viewBox="127.579 103.454 246.793 37.2836">
<defs>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g1-0"/>
<path d="M3.89738 -2.54247C3.89738 -3.39527 3.80971 -3.91333 3.5467 -4.42341C3.19601 -5.12478 2.55044 -5.30012 2.11208 -5.30012C1.10785 -5.30012 0.74122 -4.55093 0.629639 -4.32777C0.342715 -3.74595 0.326775 -2.95691 0.326775 -2.54247C0.326775 -2.01644 0.350685 -1.21146 0.73325 -0.573848C1.09988 0.0159402 1.68966 0.167372 2.11208 0.167372C2.49465 0.167372 3.18007 0.0478207 3.57858 -0.74122C3.87347 -1.31507 3.89738 -2.02441 3.89738 -2.54247ZM2.11208 -0.0557908C1.8411 -0.0557908 1.29116 -0.183313 1.12379 -1.02017C1.03611 -1.47447 1.03611 -2.22366 1.03611 -2.63811C1.03611 -3.18804 1.03611 -3.74595 1.12379 -4.18431C1.29116 -4.99726 1.91283 -5.07696 2.11208 -5.07696C2.38306 -5.07696 2.933 -4.94147 3.0924 -4.21619C3.18804 -3.77783 3.18804 -3.18007 3.18804 -2.63811C3.18804 -2.16787 3.18804 -1.45056 3.0924 -1.00423C2.92503 -0.167372 2.37509 -0.0557908 2.11208 -0.0557908Z" id="g3-48"/>
<path d="M2.11208 -3.77783C2.15193 -3.88144 2.18381 -3.93724 2.18381 -4.01694C2.18381 -4.27995 1.94471 -4.45529 1.72154 -4.45529C1.40274 -4.45529 1.31507 -4.17634 1.28319 -4.06476L0.270984 -0.629639C0.239103 -0.533998 0.239103 -0.510087 0.239103 -0.502117C0.239103 -0.430386 0.286924 -0.414446 0.366625 -0.390535C0.510087 -0.326775 0.526027 -0.326775 0.541968 -0.326775C0.565878 -0.326775 0.613699 -0.326775 0.669489 -0.462267L2.11208 -3.77783Z" id="g0-48"/>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g4-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g4-41"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g4-43"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g4-61"/>
<path d="M3.59851 -0.526027C3.39527 -0.526027 3.21594 -0.526027 3.21594 -0.585803C3.21594 -0.609714 3.41918 -1.7335 3.49091 -1.99651C3.87347 -3.52677 4.78207 -4.62665 5.82217 -4.62665C6.59925 -4.62665 6.95791 -4.04085 6.95791 -3.38331C6.95791 -2.02042 5.42765 -0.526027 3.59851 -0.526027ZM3.08443 0.0956413C3.15616 0.107597 3.27572 0.119552 3.49091 0.119552C5.45156 0.119552 7.25679 -1.76936 7.25679 -3.65828C7.25679 -4.38755 6.934 -5.27223 5.92976 -5.27223C4.20822 -5.27223 3.47895 -2.84533 2.80946 -0.597758C1.43462 -0.860772 0.860772 -1.59004 0.860772 -2.39103C0.860772 -2.71382 1.11183 -3.99303 1.80523 -4.8538C1.93674 -5.00922 1.93674 -5.03313 1.93674 -5.05704C1.93674 -5.15268 1.8411 -5.15268 1.81719 -5.15268C1.4944 -5.15268 0.585803 -3.40722 0.585803 -2.27148C0.585803 -0.932503 1.63786 -0.203238 2.60623 0.0119552L1.98456 2.03238C1.92478 2.21171 1.92478 2.23562 1.92478 2.28344C1.92478 2.57036 2.21171 2.58232 2.23562 2.58232C2.35517 2.58232 2.57036 2.5345 2.666 2.29539C2.70187 2.1878 3.03661 0.334745 3.08443 0.0956413Z" id="g2-39"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g2-58"/>
<path d="M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z" id="g2-59"/>
<path d="M4.67447 -4.49514C4.44732 -4.49514 4.33973 -4.49514 4.17235 -4.35168C4.10062 -4.29191 3.96912 -4.11258 3.96912 -3.9213C3.96912 -3.68219 4.14844 -3.53873 4.37559 -3.53873C4.66252 -3.53873 4.98531 -3.77783 4.98531 -4.25604C4.98531 -4.82989 4.43537 -5.27223 3.61046 -5.27223C2.04433 -5.27223 0.478207 -3.56264 0.478207 -1.86501C0.478207 -0.824907 1.12379 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.54222 -0.119552 1.2792 -0.836862 1.2792 -1.43462C1.2792 -1.85305 1.48244 -3.0127 1.91283 -3.82565C2.22366 -4.38755 2.86924 -5.03313 3.62242 -5.03313C3.77783 -5.03313 4.43537 -5.00922 4.67447 -4.49514Z" id="g2-99"/>
<path d="M3.38331 -1.70959C3.38331 -1.76936 3.33549 -1.81719 3.26376 -1.81719C3.15616 -1.81719 3.14421 -1.78132 3.08443 -1.57808C2.7736 -0.490162 2.28344 -0.119552 1.88892 -0.119552C1.74545 -0.119552 1.57808 -0.155417 1.57808 -0.514072C1.57808 -0.836862 1.72154 -1.19552 1.85305 -1.55417L2.68991 -3.77783C2.72578 -3.87347 2.80946 -4.08867 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.02117 2.13998 -4.63861C2.13998 -4.32777 1.98456 -3.93325 1.88892 -3.67024L1.05205 -1.44658C0.980324 -1.25529 0.908593 -1.06401 0.908593 -0.848817C0.908593 -0.310834 1.2792 0.119552 1.85305 0.119552C2.95293 0.119552 3.38331 -1.6259 3.38331 -1.70959ZM3.28767 -7.46002C3.28767 -7.63935 3.14421 -7.85455 2.8812 -7.85455C2.60623 -7.85455 2.29539 -7.59153 2.29539 -7.2807C2.29539 -6.98182 2.54645 -6.88618 2.68991 -6.88618C3.0127 -6.88618 3.28767 -7.19701 3.28767 -7.46002Z" id="g2-105"/>
<path d="M2.46276 -3.50286C2.48667 -3.5746 2.78555 -4.17235 3.2279 -4.55492C3.53873 -4.84184 3.94521 -5.03313 4.41146 -5.03313C4.88966 -5.03313 5.05704 -4.67447 5.05704 -4.19626C5.05704 -3.51482 4.56687 -2.15193 4.32777 -1.50635C4.22017 -1.21943 4.1604 -1.06401 4.1604 -0.848817C4.1604 -0.310834 4.53101 0.119552 5.10486 0.119552C6.21669 0.119552 6.63512 -1.63786 6.63512 -1.70959C6.63512 -1.76936 6.5873 -1.81719 6.51557 -1.81719C6.40797 -1.81719 6.39601 -1.78132 6.33624 -1.57808C6.06127 -0.597758 5.60697 -0.119552 5.14072 -0.119552C5.02117 -0.119552 4.82989 -0.131507 4.82989 -0.514072C4.82989 -0.812951 4.96139 -1.17161 5.03313 -1.33898C5.27223 -1.99651 5.77435 -3.33549 5.77435 -4.01694C5.77435 -4.73425 5.35592 -5.27223 4.44732 -5.27223C3.38331 -5.27223 2.82142 -4.51905 2.60623 -4.22017C2.57036 -4.90162 2.0802 -5.27223 1.55417 -5.27223C1.17161 -5.27223 0.908593 -5.04508 0.705355 -4.63861C0.490162 -4.20822 0.32279 -3.49091 0.32279 -3.44309S0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.824907 -4.35168 1.0401 -5.03313 1.51831 -5.03313C1.79328 -5.03313 1.88892 -4.84184 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.35093 0.119552 1.51831 0.0478207 1.61395 -0.131507C1.63786 -0.191283 1.74545 -0.609714 1.80523 -0.848817L2.06824 -1.92478L2.46276 -3.50286Z" id="g2-110"/>
<path d="M5.45156 -3.28767C5.45156 -4.42341 4.71034 -5.27223 3.62242 -5.27223C2.04433 -5.27223 0.490162 -3.55068 0.490162 -1.86501C0.490162 -0.729265 1.23138 0.119552 2.3193 0.119552C3.90934 0.119552 5.45156 -1.60199 5.45156 -3.28767ZM2.33126 -0.119552C1.7335 -0.119552 1.29116 -0.597758 1.29116 -1.43462C1.29116 -1.98456 1.57808 -3.20399 1.91283 -3.80174C2.45081 -4.72229 3.1203 -5.03313 3.61046 -5.03313C4.19626 -5.03313 4.65056 -4.55492 4.65056 -3.71806C4.65056 -3.23985 4.3995 -1.96065 3.94521 -1.23138C3.45504 -0.430386 2.79751 -0.119552 2.33126 -0.119552Z" id="g2-111"/>
<path d="M2.72578 -2.39103C2.92902 -2.35517 3.25181 -2.28344 3.32354 -2.27148C3.47895 -2.22366 4.01694 -2.03238 4.01694 -1.45853C4.01694 -1.08792 3.68219 -0.119552 2.29539 -0.119552C2.04433 -0.119552 1.1477 -0.155417 0.908593 -0.812951C1.3868 -0.753176 1.6259 -1.12379 1.6259 -1.3868C1.6259 -1.63786 1.45853 -1.76936 1.21943 -1.76936C0.956413 -1.76936 0.609714 -1.56613 0.609714 -1.02814C0.609714 -0.32279 1.32702 0.119552 2.28344 0.119552C4.10062 0.119552 4.63861 -1.21943 4.63861 -1.8411C4.63861 -2.02042 4.63861 -2.35517 4.25604 -2.73773C3.95716 -3.02466 3.67024 -3.08443 3.02466 -3.21594C2.70187 -3.28767 2.1878 -3.39527 2.1878 -3.93325C2.1878 -4.17235 2.40299 -5.03313 3.53873 -5.03313C4.04085 -5.03313 4.53101 -4.84184 4.65056 -4.41146C4.12453 -4.41146 4.10062 -3.95716 4.10062 -3.94521C4.10062 -3.69415 4.32777 -3.62242 4.43537 -3.62242C4.60274 -3.62242 4.93748 -3.75392 4.93748 -4.25604S4.48319 -5.27223 3.55068 -5.27223C1.98456 -5.27223 1.56613 -4.04085 1.56613 -3.55068C1.56613 -2.64209 2.45081 -2.45081 2.72578 -2.39103Z" id="g2-115"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g2-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g2-121"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.248 0 0 1.25 0 0)">
<use x="102.063" xlink:href="#g2-120" y="92.1544"/>
<use x="108.69" xlink:href="#g0-48" y="87.2182"/>
<use x="114.806" xlink:href="#g4-61" y="92.1544"/>
<use x="127.198" xlink:href="#g2-120" y="92.1544"/>
<use x="133.825" xlink:href="#g3-48" y="93.9477"/>
<use x="141.214" xlink:href="#g4-43" y="92.1544"/>
<use x="152.941" xlink:href="#g4-40" y="92.1544"/>
<use x="157.477" xlink:href="#g2-120" y="92.1544"/>
<use x="166.76" xlink:href="#g1-0" y="92.1544"/>
<use x="178.681" xlink:href="#g2-120" y="92.1544"/>
<use x="185.308" xlink:href="#g3-48" y="93.9477"/>
<use x="190.04" xlink:href="#g4-41" y="92.1544"/>
<use x="194.576" xlink:href="#g2-99" y="92.1544"/>
<use x="199.595" xlink:href="#g2-111" y="92.1544"/>
<use x="205.201" xlink:href="#g2-115" y="92.1544"/>
<use x="210.695" xlink:href="#g2-39" y="92.1544"/>
<use x="220.991" xlink:href="#g1-0" y="92.1544"/>
<use x="232.912" xlink:href="#g4-40" y="92.1544"/>
<use x="237.447" xlink:href="#g2-121" y="92.1544"/>
<use x="246.219" xlink:href="#g1-0" y="92.1544"/>
<use x="258.139" xlink:href="#g2-121" y="92.1544"/>
<use x="263.826" xlink:href="#g3-48" y="93.9477"/>
<use x="268.558" xlink:href="#g4-41" y="92.1544"/>
<use x="273.093" xlink:href="#g2-115" y="92.1544"/>
<use x="278.587" xlink:href="#g2-105" y="92.1544"/>
<use x="282.565" xlink:href="#g2-110" y="92.1544"/>
<use x="289.527" xlink:href="#g2-39" y="92.1544"/>
<use x="297.166" xlink:href="#g2-59" y="92.1544"/>
<use x="102.063" xlink:href="#g2-121" y="109.589"/>
<use x="108.178" xlink:href="#g0-48" y="104.653"/>
<use x="114.294" xlink:href="#g4-61" y="109.589"/>
<use x="126.686" xlink:href="#g2-121" y="109.589"/>
<use x="132.372" xlink:href="#g3-48" y="111.382"/>
<use x="139.761" xlink:href="#g4-43" y="109.589"/>
<use x="151.488" xlink:href="#g4-40" y="109.589"/>
<use x="156.024" xlink:href="#g2-120" y="109.589"/>
<use x="165.308" xlink:href="#g1-0" y="109.589"/>
<use x="177.228" xlink:href="#g2-120" y="109.589"/>
<use x="183.855" xlink:href="#g3-48" y="111.382"/>
<use x="188.588" xlink:href="#g4-41" y="109.589"/>
<use x="193.123" xlink:href="#g2-115" y="109.589"/>
<use x="198.616" xlink:href="#g2-105" y="109.589"/>
<use x="202.595" xlink:href="#g2-110" y="109.589"/>
<use x="209.556" xlink:href="#g2-39" y="109.589"/>
<use x="219.853" xlink:href="#g4-43" y="109.589"/>
<use x="231.58" xlink:href="#g4-40" y="109.589"/>
<use x="236.115" xlink:href="#g2-121" y="109.589"/>
<use x="244.887" xlink:href="#g1-0" y="109.589"/>
<use x="256.808" xlink:href="#g2-121" y="109.589"/>
<use x="262.494" xlink:href="#g3-48" y="111.382"/>
<use x="267.226" xlink:href="#g4-41" y="109.589"/>
<use x="271.762" xlink:href="#g2-99" y="109.589"/>
<use x="276.781" xlink:href="#g2-111" y="109.589"/>
<use x="282.387" xlink:href="#g2-115" y="109.589"/>
<use x="287.881" xlink:href="#g2-39" y="109.589"/>
<use x="295.521" xlink:href="#g2-58" y="109.589"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,86 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="242.619pt" height="59.0768pt" viewBox="128.977 103.454 242.619 59.0768">
<defs>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g1-0"/>
<path d="M3.89738 -2.54247C3.89738 -3.39527 3.80971 -3.91333 3.5467 -4.42341C3.19601 -5.12478 2.55044 -5.30012 2.11208 -5.30012C1.10785 -5.30012 0.74122 -4.55093 0.629639 -4.32777C0.342715 -3.74595 0.326775 -2.95691 0.326775 -2.54247C0.326775 -2.01644 0.350685 -1.21146 0.73325 -0.573848C1.09988 0.0159402 1.68966 0.167372 2.11208 0.167372C2.49465 0.167372 3.18007 0.0478207 3.57858 -0.74122C3.87347 -1.31507 3.89738 -2.02441 3.89738 -2.54247ZM2.11208 -0.0557908C1.8411 -0.0557908 1.29116 -0.183313 1.12379 -1.02017C1.03611 -1.47447 1.03611 -2.22366 1.03611 -2.63811C1.03611 -3.18804 1.03611 -3.74595 1.12379 -4.18431C1.29116 -4.99726 1.91283 -5.07696 2.11208 -5.07696C2.38306 -5.07696 2.933 -4.94147 3.0924 -4.21619C3.18804 -3.77783 3.18804 -3.18007 3.18804 -2.63811C3.18804 -2.16787 3.18804 -1.45056 3.0924 -1.00423C2.92503 -0.167372 2.37509 -0.0557908 2.11208 -0.0557908Z" id="g3-48"/>
<path d="M2.11208 -3.77783C2.15193 -3.88144 2.18381 -3.93724 2.18381 -4.01694C2.18381 -4.27995 1.94471 -4.45529 1.72154 -4.45529C1.40274 -4.45529 1.31507 -4.17634 1.28319 -4.06476L0.270984 -0.629639C0.239103 -0.533998 0.239103 -0.510087 0.239103 -0.502117C0.239103 -0.430386 0.286924 -0.414446 0.366625 -0.390535C0.510087 -0.326775 0.526027 -0.326775 0.541968 -0.326775C0.565878 -0.326775 0.613699 -0.326775 0.669489 -0.462267L2.11208 -3.77783Z" id="g0-48"/>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g4-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g4-41"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g4-43"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g4-61"/>
<path d="M3.59851 -0.526027C3.39527 -0.526027 3.21594 -0.526027 3.21594 -0.585803C3.21594 -0.609714 3.41918 -1.7335 3.49091 -1.99651C3.87347 -3.52677 4.78207 -4.62665 5.82217 -4.62665C6.59925 -4.62665 6.95791 -4.04085 6.95791 -3.38331C6.95791 -2.02042 5.42765 -0.526027 3.59851 -0.526027ZM3.08443 0.0956413C3.15616 0.107597 3.27572 0.119552 3.49091 0.119552C5.45156 0.119552 7.25679 -1.76936 7.25679 -3.65828C7.25679 -4.38755 6.934 -5.27223 5.92976 -5.27223C4.20822 -5.27223 3.47895 -2.84533 2.80946 -0.597758C1.43462 -0.860772 0.860772 -1.59004 0.860772 -2.39103C0.860772 -2.71382 1.11183 -3.99303 1.80523 -4.8538C1.93674 -5.00922 1.93674 -5.03313 1.93674 -5.05704C1.93674 -5.15268 1.8411 -5.15268 1.81719 -5.15268C1.4944 -5.15268 0.585803 -3.40722 0.585803 -2.27148C0.585803 -0.932503 1.63786 -0.203238 2.60623 0.0119552L1.98456 2.03238C1.92478 2.21171 1.92478 2.23562 1.92478 2.28344C1.92478 2.57036 2.21171 2.58232 2.23562 2.58232C2.35517 2.58232 2.57036 2.5345 2.666 2.29539C2.70187 2.1878 3.03661 0.334745 3.08443 0.0956413Z" id="g2-39"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g2-58"/>
<path d="M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z" id="g2-59"/>
<path d="M4.67447 -4.49514C4.44732 -4.49514 4.33973 -4.49514 4.17235 -4.35168C4.10062 -4.29191 3.96912 -4.11258 3.96912 -3.9213C3.96912 -3.68219 4.14844 -3.53873 4.37559 -3.53873C4.66252 -3.53873 4.98531 -3.77783 4.98531 -4.25604C4.98531 -4.82989 4.43537 -5.27223 3.61046 -5.27223C2.04433 -5.27223 0.478207 -3.56264 0.478207 -1.86501C0.478207 -0.824907 1.12379 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.54222 -0.119552 1.2792 -0.836862 1.2792 -1.43462C1.2792 -1.85305 1.48244 -3.0127 1.91283 -3.82565C2.22366 -4.38755 2.86924 -5.03313 3.62242 -5.03313C3.77783 -5.03313 4.43537 -5.00922 4.67447 -4.49514Z" id="g2-99"/>
<path d="M3.38331 -1.70959C3.38331 -1.76936 3.33549 -1.81719 3.26376 -1.81719C3.15616 -1.81719 3.14421 -1.78132 3.08443 -1.57808C2.7736 -0.490162 2.28344 -0.119552 1.88892 -0.119552C1.74545 -0.119552 1.57808 -0.155417 1.57808 -0.514072C1.57808 -0.836862 1.72154 -1.19552 1.85305 -1.55417L2.68991 -3.77783C2.72578 -3.87347 2.80946 -4.08867 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.02117 2.13998 -4.63861C2.13998 -4.32777 1.98456 -3.93325 1.88892 -3.67024L1.05205 -1.44658C0.980324 -1.25529 0.908593 -1.06401 0.908593 -0.848817C0.908593 -0.310834 1.2792 0.119552 1.85305 0.119552C2.95293 0.119552 3.38331 -1.6259 3.38331 -1.70959ZM3.28767 -7.46002C3.28767 -7.63935 3.14421 -7.85455 2.8812 -7.85455C2.60623 -7.85455 2.29539 -7.59153 2.29539 -7.2807C2.29539 -6.98182 2.54645 -6.88618 2.68991 -6.88618C3.0127 -6.88618 3.28767 -7.19701 3.28767 -7.46002Z" id="g2-105"/>
<path d="M2.46276 -3.50286C2.48667 -3.5746 2.78555 -4.17235 3.2279 -4.55492C3.53873 -4.84184 3.94521 -5.03313 4.41146 -5.03313C4.88966 -5.03313 5.05704 -4.67447 5.05704 -4.19626C5.05704 -3.51482 4.56687 -2.15193 4.32777 -1.50635C4.22017 -1.21943 4.1604 -1.06401 4.1604 -0.848817C4.1604 -0.310834 4.53101 0.119552 5.10486 0.119552C6.21669 0.119552 6.63512 -1.63786 6.63512 -1.70959C6.63512 -1.76936 6.5873 -1.81719 6.51557 -1.81719C6.40797 -1.81719 6.39601 -1.78132 6.33624 -1.57808C6.06127 -0.597758 5.60697 -0.119552 5.14072 -0.119552C5.02117 -0.119552 4.82989 -0.131507 4.82989 -0.514072C4.82989 -0.812951 4.96139 -1.17161 5.03313 -1.33898C5.27223 -1.99651 5.77435 -3.33549 5.77435 -4.01694C5.77435 -4.73425 5.35592 -5.27223 4.44732 -5.27223C3.38331 -5.27223 2.82142 -4.51905 2.60623 -4.22017C2.57036 -4.90162 2.0802 -5.27223 1.55417 -5.27223C1.17161 -5.27223 0.908593 -5.04508 0.705355 -4.63861C0.490162 -4.20822 0.32279 -3.49091 0.32279 -3.44309S0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.824907 -4.35168 1.0401 -5.03313 1.51831 -5.03313C1.79328 -5.03313 1.88892 -4.84184 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.35093 0.119552 1.51831 0.0478207 1.61395 -0.131507C1.63786 -0.191283 1.74545 -0.609714 1.80523 -0.848817L2.06824 -1.92478L2.46276 -3.50286Z" id="g2-110"/>
<path d="M5.45156 -3.28767C5.45156 -4.42341 4.71034 -5.27223 3.62242 -5.27223C2.04433 -5.27223 0.490162 -3.55068 0.490162 -1.86501C0.490162 -0.729265 1.23138 0.119552 2.3193 0.119552C3.90934 0.119552 5.45156 -1.60199 5.45156 -3.28767ZM2.33126 -0.119552C1.7335 -0.119552 1.29116 -0.597758 1.29116 -1.43462C1.29116 -1.98456 1.57808 -3.20399 1.91283 -3.80174C2.45081 -4.72229 3.1203 -5.03313 3.61046 -5.03313C4.19626 -5.03313 4.65056 -4.55492 4.65056 -3.71806C4.65056 -3.23985 4.3995 -1.96065 3.94521 -1.23138C3.45504 -0.430386 2.79751 -0.119552 2.33126 -0.119552Z" id="g2-111"/>
<path d="M2.72578 -2.39103C2.92902 -2.35517 3.25181 -2.28344 3.32354 -2.27148C3.47895 -2.22366 4.01694 -2.03238 4.01694 -1.45853C4.01694 -1.08792 3.68219 -0.119552 2.29539 -0.119552C2.04433 -0.119552 1.1477 -0.155417 0.908593 -0.812951C1.3868 -0.753176 1.6259 -1.12379 1.6259 -1.3868C1.6259 -1.63786 1.45853 -1.76936 1.21943 -1.76936C0.956413 -1.76936 0.609714 -1.56613 0.609714 -1.02814C0.609714 -0.32279 1.32702 0.119552 2.28344 0.119552C4.10062 0.119552 4.63861 -1.21943 4.63861 -1.8411C4.63861 -2.02042 4.63861 -2.35517 4.25604 -2.73773C3.95716 -3.02466 3.67024 -3.08443 3.02466 -3.21594C2.70187 -3.28767 2.1878 -3.39527 2.1878 -3.93325C2.1878 -4.17235 2.40299 -5.03313 3.53873 -5.03313C4.04085 -5.03313 4.53101 -4.84184 4.65056 -4.41146C4.12453 -4.41146 4.10062 -3.95716 4.10062 -3.94521C4.10062 -3.69415 4.32777 -3.62242 4.43537 -3.62242C4.60274 -3.62242 4.93748 -3.75392 4.93748 -4.25604S4.48319 -5.27223 3.55068 -5.27223C1.98456 -5.27223 1.56613 -4.04085 1.56613 -3.55068C1.56613 -2.64209 2.45081 -2.45081 2.72578 -2.39103Z" id="g2-115"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g2-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g2-121"/>
<path d="M1.51831 -0.968369C2.03238 -1.55417 2.45081 -1.92478 3.04857 -2.46276C3.76588 -3.08443 4.07671 -3.38331 4.24408 -3.56264C5.08095 -4.38755 5.49938 -5.08095 5.49938 -5.17659S5.40374 -5.27223 5.37983 -5.27223C5.29614 -5.27223 5.27223 -5.22441 5.21245 -5.14072C4.91357 -4.62665 4.62665 -4.37559 4.31582 -4.37559C4.06476 -4.37559 3.93325 -4.48319 3.7061 -4.77011C3.45504 -5.06899 3.25181 -5.27223 2.90511 -5.27223C2.03238 -5.27223 1.50635 -4.18431 1.50635 -3.93325C1.50635 -3.89738 1.51831 -3.82565 1.6259 -3.82565C1.72154 -3.82565 1.7335 -3.87347 1.76936 -3.95716C1.9726 -4.43537 2.54645 -4.51905 2.7736 -4.51905C3.02466 -4.51905 3.26376 -4.43537 3.51482 -4.32777C3.96912 -4.13649 4.1604 -4.13649 4.27995 -4.13649C4.36364 -4.13649 4.41146 -4.13649 4.47123 -4.14844C4.07671 -3.68219 3.43113 -3.10834 2.89315 -2.61818L1.68568 -1.50635C0.956413 -0.765131 0.514072 -0.0597758 0.514072 0.0239103C0.514072 0.0956413 0.573848 0.119552 0.645579 0.119552S0.729265 0.107597 0.812951 -0.0358655C1.00423 -0.334745 1.3868 -0.777086 1.82914 -0.777086C2.0802 -0.777086 2.19975 -0.6934 2.43885 -0.394521C2.666 -0.131507 2.86924 0.119552 3.25181 0.119552C4.42341 0.119552 5.0929 -1.39875 5.0929 -1.67372C5.0929 -1.72154 5.08095 -1.79328 4.96139 -1.79328C4.86575 -1.79328 4.8538 -1.74545 4.81793 -1.6259C4.55492 -0.920548 3.84956 -0.633624 3.38331 -0.633624C3.13225 -0.633624 2.89315 -0.71731 2.64209 -0.824907C2.16389 -1.01619 2.03238 -1.01619 1.87696 -1.01619C1.75741 -1.01619 1.6259 -1.01619 1.51831 -0.968369Z" id="g2-122"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.248 0 0 1.25 0 0)">
<use x="103.182" xlink:href="#g2-120" y="92.1544"/>
<use x="109.809" xlink:href="#g0-48" y="87.2182"/>
<use x="115.925" xlink:href="#g4-61" y="92.1544"/>
<use x="128.316" xlink:href="#g2-120" y="92.1544"/>
<use x="134.943" xlink:href="#g2-59" y="92.1544"/>
<use x="103.182" xlink:href="#g2-121" y="109.589"/>
<use x="109.297" xlink:href="#g0-48" y="104.653"/>
<use x="115.413" xlink:href="#g4-61" y="109.589"/>
<use x="127.804" xlink:href="#g2-121" y="109.589"/>
<use x="133.491" xlink:href="#g3-48" y="111.382"/>
<use x="140.88" xlink:href="#g4-43" y="109.589"/>
<use x="152.607" xlink:href="#g4-40" y="109.589"/>
<use x="157.142" xlink:href="#g2-121" y="109.589"/>
<use x="165.914" xlink:href="#g1-0" y="109.589"/>
<use x="177.835" xlink:href="#g2-121" y="109.589"/>
<use x="183.521" xlink:href="#g3-48" y="111.382"/>
<use x="188.253" xlink:href="#g4-41" y="109.589"/>
<use x="192.789" xlink:href="#g2-99" y="109.589"/>
<use x="197.808" xlink:href="#g2-111" y="109.589"/>
<use x="203.414" xlink:href="#g2-115" y="109.589"/>
<use x="208.908" xlink:href="#g2-39" y="109.589"/>
<use x="219.204" xlink:href="#g1-0" y="109.589"/>
<use x="231.124" xlink:href="#g4-40" y="109.589"/>
<use x="235.66" xlink:href="#g2-122" y="109.589"/>
<use x="244.267" xlink:href="#g1-0" y="109.589"/>
<use x="256.187" xlink:href="#g2-122" y="109.589"/>
<use x="261.605" xlink:href="#g3-48" y="111.382"/>
<use x="266.337" xlink:href="#g4-41" y="109.589"/>
<use x="270.872" xlink:href="#g2-115" y="109.589"/>
<use x="276.366" xlink:href="#g2-105" y="109.589"/>
<use x="280.344" xlink:href="#g2-110" y="109.589"/>
<use x="287.306" xlink:href="#g2-39" y="109.589"/>
<use x="294.946" xlink:href="#g2-59" y="109.589"/>
<use x="103.182" xlink:href="#g2-122" y="127.024"/>
<use x="109.132" xlink:href="#g0-48" y="122.087"/>
<use x="115.248" xlink:href="#g4-61" y="127.024"/>
<use x="127.639" xlink:href="#g2-122" y="127.024"/>
<use x="133.057" xlink:href="#g3-48" y="128.817"/>
<use x="140.446" xlink:href="#g4-43" y="127.024"/>
<use x="152.173" xlink:href="#g4-40" y="127.024"/>
<use x="156.708" xlink:href="#g2-121" y="127.024"/>
<use x="165.48" xlink:href="#g1-0" y="127.024"/>
<use x="177.401" xlink:href="#g2-121" y="127.024"/>
<use x="183.087" xlink:href="#g3-48" y="128.817"/>
<use x="187.82" xlink:href="#g4-41" y="127.024"/>
<use x="192.355" xlink:href="#g2-115" y="127.024"/>
<use x="197.848" xlink:href="#g2-105" y="127.024"/>
<use x="201.827" xlink:href="#g2-110" y="127.024"/>
<use x="208.788" xlink:href="#g2-39" y="127.024"/>
<use x="219.085" xlink:href="#g4-43" y="127.024"/>
<use x="230.812" xlink:href="#g4-40" y="127.024"/>
<use x="235.347" xlink:href="#g2-122" y="127.024"/>
<use x="243.954" xlink:href="#g1-0" y="127.024"/>
<use x="255.875" xlink:href="#g2-122" y="127.024"/>
<use x="261.292" xlink:href="#g3-48" y="128.817"/>
<use x="266.025" xlink:href="#g4-41" y="127.024"/>
<use x="270.56" xlink:href="#g2-99" y="127.024"/>
<use x="275.579" xlink:href="#g2-111" y="127.024"/>
<use x="281.185" xlink:href="#g2-115" y="127.024"/>
<use x="286.679" xlink:href="#g2-39" y="127.024"/>
<use x="294.319" xlink:href="#g2-58" y="127.024"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,86 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="246.251pt" height="59.0768pt" viewBox="127.76 103.454 246.251 59.0768">
<defs>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g1-0"/>
<path d="M3.89738 -2.54247C3.89738 -3.39527 3.80971 -3.91333 3.5467 -4.42341C3.19601 -5.12478 2.55044 -5.30012 2.11208 -5.30012C1.10785 -5.30012 0.74122 -4.55093 0.629639 -4.32777C0.342715 -3.74595 0.326775 -2.95691 0.326775 -2.54247C0.326775 -2.01644 0.350685 -1.21146 0.73325 -0.573848C1.09988 0.0159402 1.68966 0.167372 2.11208 0.167372C2.49465 0.167372 3.18007 0.0478207 3.57858 -0.74122C3.87347 -1.31507 3.89738 -2.02441 3.89738 -2.54247ZM2.11208 -0.0557908C1.8411 -0.0557908 1.29116 -0.183313 1.12379 -1.02017C1.03611 -1.47447 1.03611 -2.22366 1.03611 -2.63811C1.03611 -3.18804 1.03611 -3.74595 1.12379 -4.18431C1.29116 -4.99726 1.91283 -5.07696 2.11208 -5.07696C2.38306 -5.07696 2.933 -4.94147 3.0924 -4.21619C3.18804 -3.77783 3.18804 -3.18007 3.18804 -2.63811C3.18804 -2.16787 3.18804 -1.45056 3.0924 -1.00423C2.92503 -0.167372 2.37509 -0.0557908 2.11208 -0.0557908Z" id="g3-48"/>
<path d="M2.11208 -3.77783C2.15193 -3.88144 2.18381 -3.93724 2.18381 -4.01694C2.18381 -4.27995 1.94471 -4.45529 1.72154 -4.45529C1.40274 -4.45529 1.31507 -4.17634 1.28319 -4.06476L0.270984 -0.629639C0.239103 -0.533998 0.239103 -0.510087 0.239103 -0.502117C0.239103 -0.430386 0.286924 -0.414446 0.366625 -0.390535C0.510087 -0.326775 0.526027 -0.326775 0.541968 -0.326775C0.565878 -0.326775 0.613699 -0.326775 0.669489 -0.462267L2.11208 -3.77783Z" id="g0-48"/>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g4-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g4-41"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g4-43"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g4-61"/>
<path d="M3.59851 -0.526027C3.39527 -0.526027 3.21594 -0.526027 3.21594 -0.585803C3.21594 -0.609714 3.41918 -1.7335 3.49091 -1.99651C3.87347 -3.52677 4.78207 -4.62665 5.82217 -4.62665C6.59925 -4.62665 6.95791 -4.04085 6.95791 -3.38331C6.95791 -2.02042 5.42765 -0.526027 3.59851 -0.526027ZM3.08443 0.0956413C3.15616 0.107597 3.27572 0.119552 3.49091 0.119552C5.45156 0.119552 7.25679 -1.76936 7.25679 -3.65828C7.25679 -4.38755 6.934 -5.27223 5.92976 -5.27223C4.20822 -5.27223 3.47895 -2.84533 2.80946 -0.597758C1.43462 -0.860772 0.860772 -1.59004 0.860772 -2.39103C0.860772 -2.71382 1.11183 -3.99303 1.80523 -4.8538C1.93674 -5.00922 1.93674 -5.03313 1.93674 -5.05704C1.93674 -5.15268 1.8411 -5.15268 1.81719 -5.15268C1.4944 -5.15268 0.585803 -3.40722 0.585803 -2.27148C0.585803 -0.932503 1.63786 -0.203238 2.60623 0.0119552L1.98456 2.03238C1.92478 2.21171 1.92478 2.23562 1.92478 2.28344C1.92478 2.57036 2.21171 2.58232 2.23562 2.58232C2.35517 2.58232 2.57036 2.5345 2.666 2.29539C2.70187 2.1878 3.03661 0.334745 3.08443 0.0956413Z" id="g2-39"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g2-58"/>
<path d="M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z" id="g2-59"/>
<path d="M4.67447 -4.49514C4.44732 -4.49514 4.33973 -4.49514 4.17235 -4.35168C4.10062 -4.29191 3.96912 -4.11258 3.96912 -3.9213C3.96912 -3.68219 4.14844 -3.53873 4.37559 -3.53873C4.66252 -3.53873 4.98531 -3.77783 4.98531 -4.25604C4.98531 -4.82989 4.43537 -5.27223 3.61046 -5.27223C2.04433 -5.27223 0.478207 -3.56264 0.478207 -1.86501C0.478207 -0.824907 1.12379 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.54222 -0.119552 1.2792 -0.836862 1.2792 -1.43462C1.2792 -1.85305 1.48244 -3.0127 1.91283 -3.82565C2.22366 -4.38755 2.86924 -5.03313 3.62242 -5.03313C3.77783 -5.03313 4.43537 -5.00922 4.67447 -4.49514Z" id="g2-99"/>
<path d="M3.38331 -1.70959C3.38331 -1.76936 3.33549 -1.81719 3.26376 -1.81719C3.15616 -1.81719 3.14421 -1.78132 3.08443 -1.57808C2.7736 -0.490162 2.28344 -0.119552 1.88892 -0.119552C1.74545 -0.119552 1.57808 -0.155417 1.57808 -0.514072C1.57808 -0.836862 1.72154 -1.19552 1.85305 -1.55417L2.68991 -3.77783C2.72578 -3.87347 2.80946 -4.08867 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.02117 2.13998 -4.63861C2.13998 -4.32777 1.98456 -3.93325 1.88892 -3.67024L1.05205 -1.44658C0.980324 -1.25529 0.908593 -1.06401 0.908593 -0.848817C0.908593 -0.310834 1.2792 0.119552 1.85305 0.119552C2.95293 0.119552 3.38331 -1.6259 3.38331 -1.70959ZM3.28767 -7.46002C3.28767 -7.63935 3.14421 -7.85455 2.8812 -7.85455C2.60623 -7.85455 2.29539 -7.59153 2.29539 -7.2807C2.29539 -6.98182 2.54645 -6.88618 2.68991 -6.88618C3.0127 -6.88618 3.28767 -7.19701 3.28767 -7.46002Z" id="g2-105"/>
<path d="M2.46276 -3.50286C2.48667 -3.5746 2.78555 -4.17235 3.2279 -4.55492C3.53873 -4.84184 3.94521 -5.03313 4.41146 -5.03313C4.88966 -5.03313 5.05704 -4.67447 5.05704 -4.19626C5.05704 -3.51482 4.56687 -2.15193 4.32777 -1.50635C4.22017 -1.21943 4.1604 -1.06401 4.1604 -0.848817C4.1604 -0.310834 4.53101 0.119552 5.10486 0.119552C6.21669 0.119552 6.63512 -1.63786 6.63512 -1.70959C6.63512 -1.76936 6.5873 -1.81719 6.51557 -1.81719C6.40797 -1.81719 6.39601 -1.78132 6.33624 -1.57808C6.06127 -0.597758 5.60697 -0.119552 5.14072 -0.119552C5.02117 -0.119552 4.82989 -0.131507 4.82989 -0.514072C4.82989 -0.812951 4.96139 -1.17161 5.03313 -1.33898C5.27223 -1.99651 5.77435 -3.33549 5.77435 -4.01694C5.77435 -4.73425 5.35592 -5.27223 4.44732 -5.27223C3.38331 -5.27223 2.82142 -4.51905 2.60623 -4.22017C2.57036 -4.90162 2.0802 -5.27223 1.55417 -5.27223C1.17161 -5.27223 0.908593 -5.04508 0.705355 -4.63861C0.490162 -4.20822 0.32279 -3.49091 0.32279 -3.44309S0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.824907 -4.35168 1.0401 -5.03313 1.51831 -5.03313C1.79328 -5.03313 1.88892 -4.84184 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.35093 0.119552 1.51831 0.0478207 1.61395 -0.131507C1.63786 -0.191283 1.74545 -0.609714 1.80523 -0.848817L2.06824 -1.92478L2.46276 -3.50286Z" id="g2-110"/>
<path d="M5.45156 -3.28767C5.45156 -4.42341 4.71034 -5.27223 3.62242 -5.27223C2.04433 -5.27223 0.490162 -3.55068 0.490162 -1.86501C0.490162 -0.729265 1.23138 0.119552 2.3193 0.119552C3.90934 0.119552 5.45156 -1.60199 5.45156 -3.28767ZM2.33126 -0.119552C1.7335 -0.119552 1.29116 -0.597758 1.29116 -1.43462C1.29116 -1.98456 1.57808 -3.20399 1.91283 -3.80174C2.45081 -4.72229 3.1203 -5.03313 3.61046 -5.03313C4.19626 -5.03313 4.65056 -4.55492 4.65056 -3.71806C4.65056 -3.23985 4.3995 -1.96065 3.94521 -1.23138C3.45504 -0.430386 2.79751 -0.119552 2.33126 -0.119552Z" id="g2-111"/>
<path d="M2.72578 -2.39103C2.92902 -2.35517 3.25181 -2.28344 3.32354 -2.27148C3.47895 -2.22366 4.01694 -2.03238 4.01694 -1.45853C4.01694 -1.08792 3.68219 -0.119552 2.29539 -0.119552C2.04433 -0.119552 1.1477 -0.155417 0.908593 -0.812951C1.3868 -0.753176 1.6259 -1.12379 1.6259 -1.3868C1.6259 -1.63786 1.45853 -1.76936 1.21943 -1.76936C0.956413 -1.76936 0.609714 -1.56613 0.609714 -1.02814C0.609714 -0.32279 1.32702 0.119552 2.28344 0.119552C4.10062 0.119552 4.63861 -1.21943 4.63861 -1.8411C4.63861 -2.02042 4.63861 -2.35517 4.25604 -2.73773C3.95716 -3.02466 3.67024 -3.08443 3.02466 -3.21594C2.70187 -3.28767 2.1878 -3.39527 2.1878 -3.93325C2.1878 -4.17235 2.40299 -5.03313 3.53873 -5.03313C4.04085 -5.03313 4.53101 -4.84184 4.65056 -4.41146C4.12453 -4.41146 4.10062 -3.95716 4.10062 -3.94521C4.10062 -3.69415 4.32777 -3.62242 4.43537 -3.62242C4.60274 -3.62242 4.93748 -3.75392 4.93748 -4.25604S4.48319 -5.27223 3.55068 -5.27223C1.98456 -5.27223 1.56613 -4.04085 1.56613 -3.55068C1.56613 -2.64209 2.45081 -2.45081 2.72578 -2.39103Z" id="g2-115"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g2-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g2-121"/>
<path d="M1.51831 -0.968369C2.03238 -1.55417 2.45081 -1.92478 3.04857 -2.46276C3.76588 -3.08443 4.07671 -3.38331 4.24408 -3.56264C5.08095 -4.38755 5.49938 -5.08095 5.49938 -5.17659S5.40374 -5.27223 5.37983 -5.27223C5.29614 -5.27223 5.27223 -5.22441 5.21245 -5.14072C4.91357 -4.62665 4.62665 -4.37559 4.31582 -4.37559C4.06476 -4.37559 3.93325 -4.48319 3.7061 -4.77011C3.45504 -5.06899 3.25181 -5.27223 2.90511 -5.27223C2.03238 -5.27223 1.50635 -4.18431 1.50635 -3.93325C1.50635 -3.89738 1.51831 -3.82565 1.6259 -3.82565C1.72154 -3.82565 1.7335 -3.87347 1.76936 -3.95716C1.9726 -4.43537 2.54645 -4.51905 2.7736 -4.51905C3.02466 -4.51905 3.26376 -4.43537 3.51482 -4.32777C3.96912 -4.13649 4.1604 -4.13649 4.27995 -4.13649C4.36364 -4.13649 4.41146 -4.13649 4.47123 -4.14844C4.07671 -3.68219 3.43113 -3.10834 2.89315 -2.61818L1.68568 -1.50635C0.956413 -0.765131 0.514072 -0.0597758 0.514072 0.0239103C0.514072 0.0956413 0.573848 0.119552 0.645579 0.119552S0.729265 0.107597 0.812951 -0.0358655C1.00423 -0.334745 1.3868 -0.777086 1.82914 -0.777086C2.0802 -0.777086 2.19975 -0.6934 2.43885 -0.394521C2.666 -0.131507 2.86924 0.119552 3.25181 0.119552C4.42341 0.119552 5.0929 -1.39875 5.0929 -1.67372C5.0929 -1.72154 5.08095 -1.79328 4.96139 -1.79328C4.86575 -1.79328 4.8538 -1.74545 4.81793 -1.6259C4.55492 -0.920548 3.84956 -0.633624 3.38331 -0.633624C3.13225 -0.633624 2.89315 -0.71731 2.64209 -0.824907C2.16389 -1.01619 2.03238 -1.01619 1.87696 -1.01619C1.75741 -1.01619 1.6259 -1.01619 1.51831 -0.968369Z" id="g2-122"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.248 0 0 1.25 0 0)">
<use x="102.208" xlink:href="#g2-120" y="92.1544"/>
<use x="108.836" xlink:href="#g0-48" y="87.2182"/>
<use x="114.952" xlink:href="#g4-61" y="92.1544"/>
<use x="127.343" xlink:href="#g2-120" y="92.1544"/>
<use x="133.97" xlink:href="#g3-48" y="93.9477"/>
<use x="141.359" xlink:href="#g4-43" y="92.1544"/>
<use x="153.086" xlink:href="#g4-40" y="92.1544"/>
<use x="157.622" xlink:href="#g2-120" y="92.1544"/>
<use x="166.906" xlink:href="#g1-0" y="92.1544"/>
<use x="178.826" xlink:href="#g2-120" y="92.1544"/>
<use x="185.453" xlink:href="#g3-48" y="93.9477"/>
<use x="190.186" xlink:href="#g4-41" y="92.1544"/>
<use x="194.721" xlink:href="#g2-99" y="92.1544"/>
<use x="199.74" xlink:href="#g2-111" y="92.1544"/>
<use x="205.347" xlink:href="#g2-115" y="92.1544"/>
<use x="210.84" xlink:href="#g2-39" y="92.1544"/>
<use x="221.136" xlink:href="#g1-0" y="92.1544"/>
<use x="233.057" xlink:href="#g4-40" y="92.1544"/>
<use x="237.592" xlink:href="#g2-122" y="92.1544"/>
<use x="246.199" xlink:href="#g1-0" y="92.1544"/>
<use x="258.119" xlink:href="#g2-122" y="92.1544"/>
<use x="263.537" xlink:href="#g3-48" y="93.9477"/>
<use x="268.269" xlink:href="#g4-41" y="92.1544"/>
<use x="272.805" xlink:href="#g2-115" y="92.1544"/>
<use x="278.298" xlink:href="#g2-105" y="92.1544"/>
<use x="282.277" xlink:href="#g2-110" y="92.1544"/>
<use x="289.238" xlink:href="#g2-39" y="92.1544"/>
<use x="296.878" xlink:href="#g2-59" y="92.1544"/>
<use x="102.208" xlink:href="#g2-121" y="109.589"/>
<use x="108.324" xlink:href="#g0-48" y="104.653"/>
<use x="114.44" xlink:href="#g4-61" y="109.589"/>
<use x="126.831" xlink:href="#g2-121" y="109.589"/>
<use x="132.946" xlink:href="#g2-59" y="109.589"/>
<use x="102.208" xlink:href="#g2-122" y="127.024"/>
<use x="108.159" xlink:href="#g0-48" y="122.087"/>
<use x="114.275" xlink:href="#g4-61" y="127.024"/>
<use x="126.666" xlink:href="#g2-122" y="127.024"/>
<use x="132.084" xlink:href="#g3-48" y="128.817"/>
<use x="139.473" xlink:href="#g4-43" y="127.024"/>
<use x="151.2" xlink:href="#g4-40" y="127.024"/>
<use x="155.735" xlink:href="#g2-120" y="127.024"/>
<use x="165.019" xlink:href="#g1-0" y="127.024"/>
<use x="176.94" xlink:href="#g2-120" y="127.024"/>
<use x="183.567" xlink:href="#g3-48" y="128.817"/>
<use x="188.299" xlink:href="#g4-41" y="127.024"/>
<use x="192.834" xlink:href="#g2-115" y="127.024"/>
<use x="198.328" xlink:href="#g2-105" y="127.024"/>
<use x="202.306" xlink:href="#g2-110" y="127.024"/>
<use x="209.268" xlink:href="#g2-39" y="127.024"/>
<use x="219.564" xlink:href="#g4-43" y="127.024"/>
<use x="231.291" xlink:href="#g4-40" y="127.024"/>
<use x="235.827" xlink:href="#g2-122" y="127.024"/>
<use x="244.434" xlink:href="#g1-0" y="127.024"/>
<use x="256.354" xlink:href="#g2-122" y="127.024"/>
<use x="261.772" xlink:href="#g3-48" y="128.817"/>
<use x="266.504" xlink:href="#g4-41" y="127.024"/>
<use x="271.039" xlink:href="#g2-99" y="127.024"/>
<use x="276.059" xlink:href="#g2-111" y="127.024"/>
<use x="281.665" xlink:href="#g2-115" y="127.024"/>
<use x="287.158" xlink:href="#g2-39" y="127.024"/>
<use x="294.798" xlink:href="#g2-58" y="127.024"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,86 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="246.793pt" height="55.4753pt" viewBox="127.579 103.454 246.793 55.4753">
<defs>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g1-0"/>
<path d="M3.89738 -2.54247C3.89738 -3.39527 3.80971 -3.91333 3.5467 -4.42341C3.19601 -5.12478 2.55044 -5.30012 2.11208 -5.30012C1.10785 -5.30012 0.74122 -4.55093 0.629639 -4.32777C0.342715 -3.74595 0.326775 -2.95691 0.326775 -2.54247C0.326775 -2.01644 0.350685 -1.21146 0.73325 -0.573848C1.09988 0.0159402 1.68966 0.167372 2.11208 0.167372C2.49465 0.167372 3.18007 0.0478207 3.57858 -0.74122C3.87347 -1.31507 3.89738 -2.02441 3.89738 -2.54247ZM2.11208 -0.0557908C1.8411 -0.0557908 1.29116 -0.183313 1.12379 -1.02017C1.03611 -1.47447 1.03611 -2.22366 1.03611 -2.63811C1.03611 -3.18804 1.03611 -3.74595 1.12379 -4.18431C1.29116 -4.99726 1.91283 -5.07696 2.11208 -5.07696C2.38306 -5.07696 2.933 -4.94147 3.0924 -4.21619C3.18804 -3.77783 3.18804 -3.18007 3.18804 -2.63811C3.18804 -2.16787 3.18804 -1.45056 3.0924 -1.00423C2.92503 -0.167372 2.37509 -0.0557908 2.11208 -0.0557908Z" id="g3-48"/>
<path d="M2.11208 -3.77783C2.15193 -3.88144 2.18381 -3.93724 2.18381 -4.01694C2.18381 -4.27995 1.94471 -4.45529 1.72154 -4.45529C1.40274 -4.45529 1.31507 -4.17634 1.28319 -4.06476L0.270984 -0.629639C0.239103 -0.533998 0.239103 -0.510087 0.239103 -0.502117C0.239103 -0.430386 0.286924 -0.414446 0.366625 -0.390535C0.510087 -0.326775 0.526027 -0.326775 0.541968 -0.326775C0.565878 -0.326775 0.613699 -0.326775 0.669489 -0.462267L2.11208 -3.77783Z" id="g0-48"/>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g4-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g4-41"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g4-43"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g4-61"/>
<path d="M3.59851 -0.526027C3.39527 -0.526027 3.21594 -0.526027 3.21594 -0.585803C3.21594 -0.609714 3.41918 -1.7335 3.49091 -1.99651C3.87347 -3.52677 4.78207 -4.62665 5.82217 -4.62665C6.59925 -4.62665 6.95791 -4.04085 6.95791 -3.38331C6.95791 -2.02042 5.42765 -0.526027 3.59851 -0.526027ZM3.08443 0.0956413C3.15616 0.107597 3.27572 0.119552 3.49091 0.119552C5.45156 0.119552 7.25679 -1.76936 7.25679 -3.65828C7.25679 -4.38755 6.934 -5.27223 5.92976 -5.27223C4.20822 -5.27223 3.47895 -2.84533 2.80946 -0.597758C1.43462 -0.860772 0.860772 -1.59004 0.860772 -2.39103C0.860772 -2.71382 1.11183 -3.99303 1.80523 -4.8538C1.93674 -5.00922 1.93674 -5.03313 1.93674 -5.05704C1.93674 -5.15268 1.8411 -5.15268 1.81719 -5.15268C1.4944 -5.15268 0.585803 -3.40722 0.585803 -2.27148C0.585803 -0.932503 1.63786 -0.203238 2.60623 0.0119552L1.98456 2.03238C1.92478 2.21171 1.92478 2.23562 1.92478 2.28344C1.92478 2.57036 2.21171 2.58232 2.23562 2.58232C2.35517 2.58232 2.57036 2.5345 2.666 2.29539C2.70187 2.1878 3.03661 0.334745 3.08443 0.0956413Z" id="g2-39"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g2-58"/>
<path d="M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z" id="g2-59"/>
<path d="M4.67447 -4.49514C4.44732 -4.49514 4.33973 -4.49514 4.17235 -4.35168C4.10062 -4.29191 3.96912 -4.11258 3.96912 -3.9213C3.96912 -3.68219 4.14844 -3.53873 4.37559 -3.53873C4.66252 -3.53873 4.98531 -3.77783 4.98531 -4.25604C4.98531 -4.82989 4.43537 -5.27223 3.61046 -5.27223C2.04433 -5.27223 0.478207 -3.56264 0.478207 -1.86501C0.478207 -0.824907 1.12379 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.54222 -0.119552 1.2792 -0.836862 1.2792 -1.43462C1.2792 -1.85305 1.48244 -3.0127 1.91283 -3.82565C2.22366 -4.38755 2.86924 -5.03313 3.62242 -5.03313C3.77783 -5.03313 4.43537 -5.00922 4.67447 -4.49514Z" id="g2-99"/>
<path d="M3.38331 -1.70959C3.38331 -1.76936 3.33549 -1.81719 3.26376 -1.81719C3.15616 -1.81719 3.14421 -1.78132 3.08443 -1.57808C2.7736 -0.490162 2.28344 -0.119552 1.88892 -0.119552C1.74545 -0.119552 1.57808 -0.155417 1.57808 -0.514072C1.57808 -0.836862 1.72154 -1.19552 1.85305 -1.55417L2.68991 -3.77783C2.72578 -3.87347 2.80946 -4.08867 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.02117 2.13998 -4.63861C2.13998 -4.32777 1.98456 -3.93325 1.88892 -3.67024L1.05205 -1.44658C0.980324 -1.25529 0.908593 -1.06401 0.908593 -0.848817C0.908593 -0.310834 1.2792 0.119552 1.85305 0.119552C2.95293 0.119552 3.38331 -1.6259 3.38331 -1.70959ZM3.28767 -7.46002C3.28767 -7.63935 3.14421 -7.85455 2.8812 -7.85455C2.60623 -7.85455 2.29539 -7.59153 2.29539 -7.2807C2.29539 -6.98182 2.54645 -6.88618 2.68991 -6.88618C3.0127 -6.88618 3.28767 -7.19701 3.28767 -7.46002Z" id="g2-105"/>
<path d="M2.46276 -3.50286C2.48667 -3.5746 2.78555 -4.17235 3.2279 -4.55492C3.53873 -4.84184 3.94521 -5.03313 4.41146 -5.03313C4.88966 -5.03313 5.05704 -4.67447 5.05704 -4.19626C5.05704 -3.51482 4.56687 -2.15193 4.32777 -1.50635C4.22017 -1.21943 4.1604 -1.06401 4.1604 -0.848817C4.1604 -0.310834 4.53101 0.119552 5.10486 0.119552C6.21669 0.119552 6.63512 -1.63786 6.63512 -1.70959C6.63512 -1.76936 6.5873 -1.81719 6.51557 -1.81719C6.40797 -1.81719 6.39601 -1.78132 6.33624 -1.57808C6.06127 -0.597758 5.60697 -0.119552 5.14072 -0.119552C5.02117 -0.119552 4.82989 -0.131507 4.82989 -0.514072C4.82989 -0.812951 4.96139 -1.17161 5.03313 -1.33898C5.27223 -1.99651 5.77435 -3.33549 5.77435 -4.01694C5.77435 -4.73425 5.35592 -5.27223 4.44732 -5.27223C3.38331 -5.27223 2.82142 -4.51905 2.60623 -4.22017C2.57036 -4.90162 2.0802 -5.27223 1.55417 -5.27223C1.17161 -5.27223 0.908593 -5.04508 0.705355 -4.63861C0.490162 -4.20822 0.32279 -3.49091 0.32279 -3.44309S0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.824907 -4.35168 1.0401 -5.03313 1.51831 -5.03313C1.79328 -5.03313 1.88892 -4.84184 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.35093 0.119552 1.51831 0.0478207 1.61395 -0.131507C1.63786 -0.191283 1.74545 -0.609714 1.80523 -0.848817L2.06824 -1.92478L2.46276 -3.50286Z" id="g2-110"/>
<path d="M5.45156 -3.28767C5.45156 -4.42341 4.71034 -5.27223 3.62242 -5.27223C2.04433 -5.27223 0.490162 -3.55068 0.490162 -1.86501C0.490162 -0.729265 1.23138 0.119552 2.3193 0.119552C3.90934 0.119552 5.45156 -1.60199 5.45156 -3.28767ZM2.33126 -0.119552C1.7335 -0.119552 1.29116 -0.597758 1.29116 -1.43462C1.29116 -1.98456 1.57808 -3.20399 1.91283 -3.80174C2.45081 -4.72229 3.1203 -5.03313 3.61046 -5.03313C4.19626 -5.03313 4.65056 -4.55492 4.65056 -3.71806C4.65056 -3.23985 4.3995 -1.96065 3.94521 -1.23138C3.45504 -0.430386 2.79751 -0.119552 2.33126 -0.119552Z" id="g2-111"/>
<path d="M2.72578 -2.39103C2.92902 -2.35517 3.25181 -2.28344 3.32354 -2.27148C3.47895 -2.22366 4.01694 -2.03238 4.01694 -1.45853C4.01694 -1.08792 3.68219 -0.119552 2.29539 -0.119552C2.04433 -0.119552 1.1477 -0.155417 0.908593 -0.812951C1.3868 -0.753176 1.6259 -1.12379 1.6259 -1.3868C1.6259 -1.63786 1.45853 -1.76936 1.21943 -1.76936C0.956413 -1.76936 0.609714 -1.56613 0.609714 -1.02814C0.609714 -0.32279 1.32702 0.119552 2.28344 0.119552C4.10062 0.119552 4.63861 -1.21943 4.63861 -1.8411C4.63861 -2.02042 4.63861 -2.35517 4.25604 -2.73773C3.95716 -3.02466 3.67024 -3.08443 3.02466 -3.21594C2.70187 -3.28767 2.1878 -3.39527 2.1878 -3.93325C2.1878 -4.17235 2.40299 -5.03313 3.53873 -5.03313C4.04085 -5.03313 4.53101 -4.84184 4.65056 -4.41146C4.12453 -4.41146 4.10062 -3.95716 4.10062 -3.94521C4.10062 -3.69415 4.32777 -3.62242 4.43537 -3.62242C4.60274 -3.62242 4.93748 -3.75392 4.93748 -4.25604S4.48319 -5.27223 3.55068 -5.27223C1.98456 -5.27223 1.56613 -4.04085 1.56613 -3.55068C1.56613 -2.64209 2.45081 -2.45081 2.72578 -2.39103Z" id="g2-115"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g2-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g2-121"/>
<path d="M1.51831 -0.968369C2.03238 -1.55417 2.45081 -1.92478 3.04857 -2.46276C3.76588 -3.08443 4.07671 -3.38331 4.24408 -3.56264C5.08095 -4.38755 5.49938 -5.08095 5.49938 -5.17659S5.40374 -5.27223 5.37983 -5.27223C5.29614 -5.27223 5.27223 -5.22441 5.21245 -5.14072C4.91357 -4.62665 4.62665 -4.37559 4.31582 -4.37559C4.06476 -4.37559 3.93325 -4.48319 3.7061 -4.77011C3.45504 -5.06899 3.25181 -5.27223 2.90511 -5.27223C2.03238 -5.27223 1.50635 -4.18431 1.50635 -3.93325C1.50635 -3.89738 1.51831 -3.82565 1.6259 -3.82565C1.72154 -3.82565 1.7335 -3.87347 1.76936 -3.95716C1.9726 -4.43537 2.54645 -4.51905 2.7736 -4.51905C3.02466 -4.51905 3.26376 -4.43537 3.51482 -4.32777C3.96912 -4.13649 4.1604 -4.13649 4.27995 -4.13649C4.36364 -4.13649 4.41146 -4.13649 4.47123 -4.14844C4.07671 -3.68219 3.43113 -3.10834 2.89315 -2.61818L1.68568 -1.50635C0.956413 -0.765131 0.514072 -0.0597758 0.514072 0.0239103C0.514072 0.0956413 0.573848 0.119552 0.645579 0.119552S0.729265 0.107597 0.812951 -0.0358655C1.00423 -0.334745 1.3868 -0.777086 1.82914 -0.777086C2.0802 -0.777086 2.19975 -0.6934 2.43885 -0.394521C2.666 -0.131507 2.86924 0.119552 3.25181 0.119552C4.42341 0.119552 5.0929 -1.39875 5.0929 -1.67372C5.0929 -1.72154 5.08095 -1.79328 4.96139 -1.79328C4.86575 -1.79328 4.8538 -1.74545 4.81793 -1.6259C4.55492 -0.920548 3.84956 -0.633624 3.38331 -0.633624C3.13225 -0.633624 2.89315 -0.71731 2.64209 -0.824907C2.16389 -1.01619 2.03238 -1.01619 1.87696 -1.01619C1.75741 -1.01619 1.6259 -1.01619 1.51831 -0.968369Z" id="g2-122"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.248 0 0 1.25 0 0)">
<use x="102.063" xlink:href="#g2-120" y="92.1544"/>
<use x="108.69" xlink:href="#g0-48" y="87.2182"/>
<use x="114.806" xlink:href="#g4-61" y="92.1544"/>
<use x="127.198" xlink:href="#g2-120" y="92.1544"/>
<use x="133.825" xlink:href="#g3-48" y="93.9477"/>
<use x="141.214" xlink:href="#g4-43" y="92.1544"/>
<use x="152.941" xlink:href="#g4-40" y="92.1544"/>
<use x="157.477" xlink:href="#g2-120" y="92.1544"/>
<use x="166.76" xlink:href="#g1-0" y="92.1544"/>
<use x="178.681" xlink:href="#g2-120" y="92.1544"/>
<use x="185.308" xlink:href="#g3-48" y="93.9477"/>
<use x="190.04" xlink:href="#g4-41" y="92.1544"/>
<use x="194.576" xlink:href="#g2-99" y="92.1544"/>
<use x="199.595" xlink:href="#g2-111" y="92.1544"/>
<use x="205.201" xlink:href="#g2-115" y="92.1544"/>
<use x="210.695" xlink:href="#g2-39" y="92.1544"/>
<use x="220.991" xlink:href="#g1-0" y="92.1544"/>
<use x="232.912" xlink:href="#g4-40" y="92.1544"/>
<use x="237.447" xlink:href="#g2-121" y="92.1544"/>
<use x="246.219" xlink:href="#g1-0" y="92.1544"/>
<use x="258.139" xlink:href="#g2-121" y="92.1544"/>
<use x="263.826" xlink:href="#g3-48" y="93.9477"/>
<use x="268.558" xlink:href="#g4-41" y="92.1544"/>
<use x="273.093" xlink:href="#g2-115" y="92.1544"/>
<use x="278.587" xlink:href="#g2-105" y="92.1544"/>
<use x="282.565" xlink:href="#g2-110" y="92.1544"/>
<use x="289.527" xlink:href="#g2-39" y="92.1544"/>
<use x="297.166" xlink:href="#g2-59" y="92.1544"/>
<use x="102.063" xlink:href="#g2-121" y="109.589"/>
<use x="108.178" xlink:href="#g0-48" y="104.653"/>
<use x="114.294" xlink:href="#g4-61" y="109.589"/>
<use x="126.686" xlink:href="#g2-121" y="109.589"/>
<use x="132.372" xlink:href="#g3-48" y="111.382"/>
<use x="139.761" xlink:href="#g4-43" y="109.589"/>
<use x="151.488" xlink:href="#g4-40" y="109.589"/>
<use x="156.024" xlink:href="#g2-120" y="109.589"/>
<use x="165.308" xlink:href="#g1-0" y="109.589"/>
<use x="177.228" xlink:href="#g2-120" y="109.589"/>
<use x="183.855" xlink:href="#g3-48" y="111.382"/>
<use x="188.588" xlink:href="#g4-41" y="109.589"/>
<use x="193.123" xlink:href="#g2-115" y="109.589"/>
<use x="198.616" xlink:href="#g2-105" y="109.589"/>
<use x="202.595" xlink:href="#g2-110" y="109.589"/>
<use x="209.556" xlink:href="#g2-39" y="109.589"/>
<use x="219.853" xlink:href="#g4-43" y="109.589"/>
<use x="231.58" xlink:href="#g4-40" y="109.589"/>
<use x="236.115" xlink:href="#g2-121" y="109.589"/>
<use x="244.887" xlink:href="#g1-0" y="109.589"/>
<use x="256.808" xlink:href="#g2-121" y="109.589"/>
<use x="262.494" xlink:href="#g3-48" y="111.382"/>
<use x="267.226" xlink:href="#g4-41" y="109.589"/>
<use x="271.762" xlink:href="#g2-99" y="109.589"/>
<use x="276.781" xlink:href="#g2-111" y="109.589"/>
<use x="282.387" xlink:href="#g2-115" y="109.589"/>
<use x="287.881" xlink:href="#g2-39" y="109.589"/>
<use x="295.521" xlink:href="#g2-59" y="109.589"/>
<use x="102.063" xlink:href="#g2-122" y="127.024"/>
<use x="108.013" xlink:href="#g0-48" y="122.087"/>
<use x="114.129" xlink:href="#g4-61" y="127.024"/>
<use x="126.521" xlink:href="#g2-122" y="127.024"/>
<use x="132.471" xlink:href="#g2-58" y="127.024"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,60 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="319.911pt" height="17.9328pt" viewBox="130.706 101.089 319.911 17.9328">
<defs>
<path d="M3.89738 -2.54247C3.89738 -3.39527 3.80971 -3.91333 3.5467 -4.42341C3.19601 -5.12478 2.55044 -5.30012 2.11208 -5.30012C1.10785 -5.30012 0.74122 -4.55093 0.629639 -4.32777C0.342715 -3.74595 0.326775 -2.95691 0.326775 -2.54247C0.326775 -2.01644 0.350685 -1.21146 0.73325 -0.573848C1.09988 0.0159402 1.68966 0.167372 2.11208 0.167372C2.49465 0.167372 3.18007 0.0478207 3.57858 -0.74122C3.87347 -1.31507 3.89738 -2.02441 3.89738 -2.54247ZM2.11208 -0.0557908C1.8411 -0.0557908 1.29116 -0.183313 1.12379 -1.02017C1.03611 -1.47447 1.03611 -2.22366 1.03611 -2.63811C1.03611 -3.18804 1.03611 -3.74595 1.12379 -4.18431C1.29116 -4.99726 1.91283 -5.07696 2.11208 -5.07696C2.38306 -5.07696 2.933 -4.94147 3.0924 -4.21619C3.18804 -3.77783 3.18804 -3.18007 3.18804 -2.63811C3.18804 -2.16787 3.18804 -1.45056 3.0924 -1.00423C2.92503 -0.167372 2.37509 -0.0557908 2.11208 -0.0557908Z" id="g4-48"/>
<path d="M2.24757 -1.6259C2.37509 -1.74545 2.70984 -2.00847 2.83736 -2.12005C3.33151 -2.57435 3.80174 -3.0127 3.80174 -3.73798C3.80174 -4.68643 3.00473 -5.30012 2.00847 -5.30012C1.05205 -5.30012 0.422416 -4.57484 0.422416 -3.8655C0.422416 -3.47497 0.73325 -3.41918 0.844832 -3.41918C1.0122 -3.41918 1.25928 -3.53873 1.25928 -3.84159C1.25928 -4.25604 0.860772 -4.25604 0.765131 -4.25604C0.996264 -4.83786 1.53026 -5.03711 1.9208 -5.03711C2.66202 -5.03711 3.04458 -4.40747 3.04458 -3.73798C3.04458 -2.90909 2.46276 -2.30336 1.52229 -1.33898L0.518057 -0.302864C0.422416 -0.215193 0.422416 -0.199253 0.422416 0H3.57061L3.80174 -1.42665H3.55467C3.53076 -1.26725 3.467 -0.868742 3.37136 -0.71731C3.32354 -0.653549 2.71781 -0.653549 2.59029 -0.653549H1.17161L2.24757 -1.6259Z" id="g4-50"/>
<path d="M5.06899 13.868C5.4396 13.868 5.45156 13.856 5.57111 13.6289L12.1106 -0.0239103C12.1943 -0.179328 12.1943 -0.203238 12.1943 -0.239103C12.1943 -0.37061 12.0986 -0.478207 11.9552 -0.478207C11.7998 -0.478207 11.7519 -0.37061 11.6922 -0.239103L5.52329 12.6247L2.97684 6.69489L1.31507 7.9741L1.4944 8.16538L2.34321 7.5198L5.06899 13.868Z" id="g0-112"/>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g1-0"/>
<path d="M3.96115 -2.90112C3.96115 -3.52279 3.60249 -3.52279 3.57061 -3.52279C3.37933 -3.52279 3.15616 -3.31557 3.15616 -3.10834C3.15616 -2.98082 3.21993 -2.92503 3.29166 -2.86127C3.47497 -2.70187 3.58655 -2.4787 3.58655 -2.22366C3.58655 -1.85704 3.06052 -0.143462 2.14396 -0.143462C1.80125 -0.143462 1.52229 -0.326775 1.52229 -0.828892C1.52229 -1.26725 1.76139 -1.89689 1.95268 -2.37509C2.04832 -2.63014 2.07223 -2.6939 2.07223 -2.83736C2.07223 -3.26775 1.72154 -3.51482 1.35492 -3.51482C0.565878 -3.51482 0.239103 -2.39103 0.239103 -2.29539C0.239103 -2.22366 0.294894 -2.19178 0.358655 -2.19178C0.462267 -2.19178 0.470237 -2.2396 0.494147 -2.3193C0.70137 -3.0127 1.04408 -3.29166 1.33101 -3.29166C1.45056 -3.29166 1.52229 -3.21993 1.52229 -3.02864C1.52229 -2.84533 1.45056 -2.66202 1.37086 -2.46276C0.980324 -1.45853 0.948443 -1.19552 0.948443 -0.948443C0.948443 -0.0797011 1.65778 0.0797011 2.11208 0.0797011C3.43512 0.0797011 3.96115 -2.29539 3.96115 -2.90112Z" id="g2-118"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g3-58"/>
<path d="M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z" id="g3-59"/>
<path d="M6.01345 -7.99801C6.0254 -8.04583 6.04932 -8.11756 6.04932 -8.17733C6.04932 -8.29689 5.92976 -8.29689 5.90585 -8.29689C5.8939 -8.29689 5.30809 -8.24907 5.24832 -8.23711C5.04508 -8.22516 4.86575 -8.20125 4.65056 -8.18929C4.35168 -8.16538 4.268 -8.15342 4.268 -7.93823C4.268 -7.81868 4.36364 -7.81868 4.53101 -7.81868C5.11681 -7.81868 5.12877 -7.71108 5.12877 -7.59153C5.12877 -7.5198 5.10486 -7.42416 5.0929 -7.38829L4.36364 -4.48319C4.23213 -4.79402 3.90934 -5.27223 3.28767 -5.27223C1.93674 -5.27223 0.478207 -3.52677 0.478207 -1.75741C0.478207 -0.573848 1.17161 0.119552 1.98456 0.119552C2.64209 0.119552 3.20399 -0.394521 3.53873 -0.789041C3.65828 -0.0836862 4.22017 0.119552 4.57883 0.119552S5.22441 -0.0956413 5.4396 -0.526027C5.63088 -0.932503 5.79826 -1.66177 5.79826 -1.70959C5.79826 -1.76936 5.75044 -1.81719 5.6787 -1.81719C5.57111 -1.81719 5.55915 -1.75741 5.51133 -1.57808C5.332 -0.872727 5.10486 -0.119552 4.61469 -0.119552C4.268 -0.119552 4.24408 -0.430386 4.24408 -0.669489C4.24408 -0.71731 4.24408 -0.968369 4.32777 -1.30311L6.01345 -7.99801ZM3.59851 -1.42267C3.53873 -1.21943 3.53873 -1.19552 3.37136 -0.968369C3.10834 -0.633624 2.58232 -0.119552 2.02042 -0.119552C1.53026 -0.119552 1.25529 -0.561893 1.25529 -1.26725C1.25529 -1.92478 1.6259 -3.26376 1.85305 -3.76588C2.25953 -4.60274 2.82142 -5.03313 3.28767 -5.03313C4.07671 -5.03313 4.23213 -4.0528 4.23213 -3.95716C4.23213 -3.94521 4.19626 -3.78979 4.18431 -3.76588L3.59851 -1.42267Z" id="g3-100"/>
<path d="M2.40299 -4.80598H3.50286C3.73001 -4.80598 3.84956 -4.80598 3.84956 -5.02117C3.84956 -5.15268 3.77783 -5.15268 3.53873 -5.15268H2.48667L2.92902 -6.89813C2.97684 -7.0655 2.97684 -7.08941 2.97684 -7.1731C2.97684 -7.36438 2.82142 -7.47198 2.666 -7.47198C2.57036 -7.47198 2.29539 -7.43611 2.19975 -7.05355L1.7335 -5.15268H0.609714C0.37061 -5.15268 0.263014 -5.15268 0.263014 -4.92553C0.263014 -4.80598 0.3467 -4.80598 0.573848 -4.80598H1.63786L0.848817 -1.64981C0.753176 -1.23138 0.71731 -1.11183 0.71731 -0.956413C0.71731 -0.394521 1.11183 0.119552 1.78132 0.119552C2.98879 0.119552 3.63437 -1.6259 3.63437 -1.70959C3.63437 -1.78132 3.58655 -1.81719 3.51482 -1.81719C3.49091 -1.81719 3.44309 -1.81719 3.41918 -1.76936C3.40722 -1.75741 3.39527 -1.74545 3.31158 -1.55417C3.06052 -0.956413 2.51059 -0.119552 1.81719 -0.119552C1.45853 -0.119552 1.43462 -0.418431 1.43462 -0.681445C1.43462 -0.6934 1.43462 -0.920548 1.47049 -1.06401L2.40299 -4.80598Z" id="g3-116"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g3-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g3-121"/>
<path d="M1.51831 -0.968369C2.03238 -1.55417 2.45081 -1.92478 3.04857 -2.46276C3.76588 -3.08443 4.07671 -3.38331 4.24408 -3.56264C5.08095 -4.38755 5.49938 -5.08095 5.49938 -5.17659S5.40374 -5.27223 5.37983 -5.27223C5.29614 -5.27223 5.27223 -5.22441 5.21245 -5.14072C4.91357 -4.62665 4.62665 -4.37559 4.31582 -4.37559C4.06476 -4.37559 3.93325 -4.48319 3.7061 -4.77011C3.45504 -5.06899 3.25181 -5.27223 2.90511 -5.27223C2.03238 -5.27223 1.50635 -4.18431 1.50635 -3.93325C1.50635 -3.89738 1.51831 -3.82565 1.6259 -3.82565C1.72154 -3.82565 1.7335 -3.87347 1.76936 -3.95716C1.9726 -4.43537 2.54645 -4.51905 2.7736 -4.51905C3.02466 -4.51905 3.26376 -4.43537 3.51482 -4.32777C3.96912 -4.13649 4.1604 -4.13649 4.27995 -4.13649C4.36364 -4.13649 4.41146 -4.13649 4.47123 -4.14844C4.07671 -3.68219 3.43113 -3.10834 2.89315 -2.61818L1.68568 -1.50635C0.956413 -0.765131 0.514072 -0.0597758 0.514072 0.0239103C0.514072 0.0956413 0.573848 0.119552 0.645579 0.119552S0.729265 0.107597 0.812951 -0.0358655C1.00423 -0.334745 1.3868 -0.777086 1.82914 -0.777086C2.0802 -0.777086 2.19975 -0.6934 2.43885 -0.394521C2.666 -0.131507 2.86924 0.119552 3.25181 0.119552C4.42341 0.119552 5.0929 -1.39875 5.0929 -1.67372C5.0929 -1.72154 5.08095 -1.79328 4.96139 -1.79328C4.86575 -1.79328 4.8538 -1.74545 4.81793 -1.6259C4.55492 -0.920548 3.84956 -0.633624 3.38331 -0.633624C3.13225 -0.633624 2.89315 -0.71731 2.64209 -0.824907C2.16389 -1.01619 2.03238 -1.01619 1.87696 -1.01619C1.75741 -1.01619 1.6259 -1.01619 1.51831 -0.968369Z" id="g3-122"/>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g5-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g5-41"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g5-43"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g5-61"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.25 0 0 1.25 0 0)">
<use x="104.565" xlink:href="#g3-100" y="92.1544"/>
<use x="110.625" xlink:href="#g5-40" y="92.1544"/>
<use x="115.16" xlink:href="#g3-116" y="92.1544"/>
<use x="119.372" xlink:href="#g3-59" y="92.1544"/>
<use x="124.604" xlink:href="#g3-100" y="92.1544"/>
<use x="130.663" xlink:href="#g4-48" y="93.9477"/>
<use x="135.396" xlink:href="#g5-41" y="92.1544"/>
<use x="143.252" xlink:href="#g5-61" y="92.1544"/>
<use x="155.643" xlink:href="#g0-112" y="81.349"/>
<rect height="0.478187" width="190.695" x="167.599" y="80.8709"/>
<use x="167.599" xlink:href="#g5-40" y="92.1544"/>
<use x="172.134" xlink:href="#g3-120" y="92.1544"/>
<use x="181.418" xlink:href="#g1-0" y="92.1544"/>
<use x="193.338" xlink:href="#g3-120" y="92.1544"/>
<use x="199.965" xlink:href="#g2-118" y="93.9477"/>
<use x="204.873" xlink:href="#g5-41" y="92.1544"/>
<use x="209.408" xlink:href="#g4-50" y="88.7007"/>
<use x="216.797" xlink:href="#g5-43" y="92.1544"/>
<use x="228.525" xlink:href="#g5-40" y="92.1544"/>
<use x="233.06" xlink:href="#g3-121" y="92.1544"/>
<use x="241.832" xlink:href="#g1-0" y="92.1544"/>
<use x="253.752" xlink:href="#g3-121" y="92.1544"/>
<use x="259.439" xlink:href="#g2-118" y="93.9477"/>
<use x="264.346" xlink:href="#g5-41" y="92.1544"/>
<use x="268.882" xlink:href="#g4-50" y="88.7007"/>
<use x="276.271" xlink:href="#g5-43" y="92.1544"/>
<use x="287.998" xlink:href="#g5-40" y="92.1544"/>
<use x="292.533" xlink:href="#g3-122" y="92.1544"/>
<use x="301.14" xlink:href="#g1-0" y="92.1544"/>
<use x="313.061" xlink:href="#g3-122" y="92.1544"/>
<use x="318.478" xlink:href="#g2-118" y="93.9477"/>
<use x="326.042" xlink:href="#g5-43" y="92.1544"/>
<use x="337.77" xlink:href="#g3-100" y="92.1544"/>
<use x="343.83" xlink:href="#g4-48" y="93.9477"/>
<use x="348.562" xlink:href="#g5-41" y="92.1544"/>
<use x="353.097" xlink:href="#g4-50" y="88.7007"/>
<use x="358.294" xlink:href="#g3-58" y="92.1544"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,46 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="137.171pt" height="35.3194pt" viewBox="222.89 98.3811 137.171 35.3194">
<defs>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g3-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g3-41"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g3-61"/>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g0-0"/>
<path d="M2.50262 -5.07696C2.50262 -5.29215 2.48667 -5.30012 2.27148 -5.30012C1.94471 -4.98132 1.52229 -4.79004 0.765131 -4.79004V-4.52702C0.980324 -4.52702 1.41071 -4.52702 1.87298 -4.74222V-0.653549C1.87298 -0.358655 1.84907 -0.263014 1.09191 -0.263014H0.812951V0C1.13973 -0.0239103 1.82516 -0.0239103 2.18381 -0.0239103S3.23587 -0.0239103 3.56264 0V-0.263014H3.28369C2.52653 -0.263014 2.50262 -0.358655 2.50262 -0.653549V-5.07696Z" id="g2-49"/>
<path d="M2.24757 -1.6259C2.37509 -1.74545 2.70984 -2.00847 2.83736 -2.12005C3.33151 -2.57435 3.80174 -3.0127 3.80174 -3.73798C3.80174 -4.68643 3.00473 -5.30012 2.00847 -5.30012C1.05205 -5.30012 0.422416 -4.57484 0.422416 -3.8655C0.422416 -3.47497 0.73325 -3.41918 0.844832 -3.41918C1.0122 -3.41918 1.25928 -3.53873 1.25928 -3.84159C1.25928 -4.25604 0.860772 -4.25604 0.765131 -4.25604C0.996264 -4.83786 1.53026 -5.03711 1.9208 -5.03711C2.66202 -5.03711 3.04458 -4.40747 3.04458 -3.73798C3.04458 -2.90909 2.46276 -2.30336 1.52229 -1.33898L0.518057 -0.302864C0.422416 -0.215193 0.422416 -0.199253 0.422416 0H3.57061L3.80174 -1.42665H3.55467C3.53076 -1.26725 3.467 -0.868742 3.37136 -0.71731C3.32354 -0.653549 2.71781 -0.653549 2.59029 -0.653549H1.17161L2.24757 -1.6259Z" id="g2-50"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g1-58"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g1-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g1-121"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.25 0 0 1.25 0 0)">
<use x="178.312" xlink:href="#g3-40" y="87.6712"/>
<use x="182.847" xlink:href="#g1-120" y="87.6712"/>
<use x="192.131" xlink:href="#g0-0" y="87.6712"/>
<use x="204.052" xlink:href="#g1-120" y="87.6712"/>
<use x="210.679" xlink:href="#g2-49" y="89.4645"/>
<use x="215.411" xlink:href="#g3-41" y="87.6712"/>
<rect height="0.478187" width="41.753" x="178.312" y="92.5311"/>
<use x="179.042" xlink:href="#g3-40" y="103.96"/>
<use x="183.577" xlink:href="#g1-121" y="103.96"/>
<use x="192.349" xlink:href="#g0-0" y="103.96"/>
<use x="204.27" xlink:href="#g1-121" y="103.96"/>
<use x="209.956" xlink:href="#g2-49" y="105.753"/>
<use x="214.689" xlink:href="#g3-41" y="103.96"/>
<use x="224.581" xlink:href="#g3-61" y="95.759"/>
<use x="238.168" xlink:href="#g3-40" y="87.6712"/>
<use x="242.704" xlink:href="#g1-120" y="87.6712"/>
<use x="249.331" xlink:href="#g2-50" y="89.4645"/>
<use x="256.72" xlink:href="#g0-0" y="87.6712"/>
<use x="268.64" xlink:href="#g1-120" y="87.6712"/>
<use x="275.268" xlink:href="#g2-49" y="89.4645"/>
<use x="280" xlink:href="#g3-41" y="87.6712"/>
<rect height="0.478187" width="46.4853" x="238.168" y="92.5311"/>
<use x="239.113" xlink:href="#g3-40" y="103.96"/>
<use x="243.648" xlink:href="#g1-121" y="103.96"/>
<use x="249.335" xlink:href="#g2-50" y="105.753"/>
<use x="256.724" xlink:href="#g0-0" y="103.96"/>
<use x="268.644" xlink:href="#g1-121" y="103.96"/>
<use x="274.33" xlink:href="#g2-49" y="105.753"/>
<use x="279.063" xlink:href="#g3-41" y="103.96"/>
<use x="285.849" xlink:href="#g1-58" y="95.759"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8 KiB

View file

@ -0,0 +1,40 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="123.97pt" height="37.2836pt" viewBox="48.5679 103.454 123.97 37.2836">
<defs>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g1-0"/>
<path d="M3.96115 -2.90112C3.96115 -3.52279 3.60249 -3.52279 3.57061 -3.52279C3.37933 -3.52279 3.15616 -3.31557 3.15616 -3.10834C3.15616 -2.98082 3.21993 -2.92503 3.29166 -2.86127C3.47497 -2.70187 3.58655 -2.4787 3.58655 -2.22366C3.58655 -1.85704 3.06052 -0.143462 2.14396 -0.143462C1.80125 -0.143462 1.52229 -0.326775 1.52229 -0.828892C1.52229 -1.26725 1.76139 -1.89689 1.95268 -2.37509C2.04832 -2.63014 2.07223 -2.6939 2.07223 -2.83736C2.07223 -3.26775 1.72154 -3.51482 1.35492 -3.51482C0.565878 -3.51482 0.239103 -2.39103 0.239103 -2.29539C0.239103 -2.22366 0.294894 -2.19178 0.358655 -2.19178C0.462267 -2.19178 0.470237 -2.2396 0.494147 -2.3193C0.70137 -3.0127 1.04408 -3.29166 1.33101 -3.29166C1.45056 -3.29166 1.52229 -3.21993 1.52229 -3.02864C1.52229 -2.84533 1.45056 -2.66202 1.37086 -2.46276C0.980324 -1.45853 0.948443 -1.19552 0.948443 -0.948443C0.948443 -0.0797011 1.65778 0.0797011 2.11208 0.0797011C3.43512 0.0797011 3.96115 -2.29539 3.96115 -2.90112Z" id="g2-118"/>
<path d="M2.11208 -3.77783C2.15193 -3.88144 2.18381 -3.93724 2.18381 -4.01694C2.18381 -4.27995 1.94471 -4.45529 1.72154 -4.45529C1.40274 -4.45529 1.31507 -4.17634 1.28319 -4.06476L0.270984 -0.629639C0.239103 -0.533998 0.239103 -0.510087 0.239103 -0.502117C0.239103 -0.430386 0.286924 -0.414446 0.366625 -0.390535C0.510087 -0.326775 0.526027 -0.326775 0.541968 -0.326775C0.565878 -0.326775 0.613699 -0.326775 0.669489 -0.462267L2.11208 -3.77783Z" id="g0-48"/>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g4-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g4-41"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g4-43"/>
<path d="M4.31582 -7.78281C4.31582 -8.00996 4.31582 -8.06974 4.14844 -8.06974C4.0528 -8.06974 4.01694 -8.06974 3.9213 -7.92628L0.32279 -2.34321V-1.99651H3.467V-0.908593C3.467 -0.466252 3.44309 -0.3467 2.57036 -0.3467H2.33126V0C2.60623 -0.0239103 3.55068 -0.0239103 3.88543 -0.0239103S5.17659 -0.0239103 5.45156 0V-0.3467H5.21245C4.35168 -0.3467 4.31582 -0.466252 4.31582 -0.908593V-1.99651H5.52329V-2.34321H4.31582V-7.78281ZM3.52677 -6.85031V-2.34321H0.621669L3.52677 -6.85031Z" id="g4-52"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g4-61"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g3-58"/>
<path d="M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z" id="g3-59"/>
<path d="M5.12877 -8.52403C5.12877 -8.53599 5.2005 -8.71532 5.2005 -8.73923C5.2005 -8.88269 5.08095 -8.96638 4.98531 -8.96638C4.92553 -8.96638 4.81793 -8.96638 4.72229 -8.70336L0.71731 2.54645C0.71731 2.55841 0.645579 2.73773 0.645579 2.76164C0.645579 2.90511 0.765131 2.98879 0.860772 2.98879C0.932503 2.98879 1.0401 2.97684 1.12379 2.72578L5.12877 -8.52403Z" id="g3-61"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g3-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g3-121"/>
<path d="M1.51831 -0.968369C2.03238 -1.55417 2.45081 -1.92478 3.04857 -2.46276C3.76588 -3.08443 4.07671 -3.38331 4.24408 -3.56264C5.08095 -4.38755 5.49938 -5.08095 5.49938 -5.17659S5.40374 -5.27223 5.37983 -5.27223C5.29614 -5.27223 5.27223 -5.22441 5.21245 -5.14072C4.91357 -4.62665 4.62665 -4.37559 4.31582 -4.37559C4.06476 -4.37559 3.93325 -4.48319 3.7061 -4.77011C3.45504 -5.06899 3.25181 -5.27223 2.90511 -5.27223C2.03238 -5.27223 1.50635 -4.18431 1.50635 -3.93325C1.50635 -3.89738 1.51831 -3.82565 1.6259 -3.82565C1.72154 -3.82565 1.7335 -3.87347 1.76936 -3.95716C1.9726 -4.43537 2.54645 -4.51905 2.7736 -4.51905C3.02466 -4.51905 3.26376 -4.43537 3.51482 -4.32777C3.96912 -4.13649 4.1604 -4.13649 4.27995 -4.13649C4.36364 -4.13649 4.41146 -4.13649 4.47123 -4.14844C4.07671 -3.68219 3.43113 -3.10834 2.89315 -2.61818L1.68568 -1.50635C0.956413 -0.765131 0.514072 -0.0597758 0.514072 0.0239103C0.514072 0.0956413 0.573848 0.119552 0.645579 0.119552S0.729265 0.107597 0.812951 -0.0358655C1.00423 -0.334745 1.3868 -0.777086 1.82914 -0.777086C2.0802 -0.777086 2.19975 -0.6934 2.43885 -0.394521C2.666 -0.131507 2.86924 0.119552 3.25181 0.119552C4.42341 0.119552 5.0929 -1.39875 5.0929 -1.67372C5.0929 -1.72154 5.08095 -1.79328 4.96139 -1.79328C4.86575 -1.79328 4.8538 -1.74545 4.81793 -1.6259C4.55492 -0.920548 3.84956 -0.633624 3.38331 -0.633624C3.13225 -0.633624 2.89315 -0.71731 2.64209 -0.824907C2.16389 -1.01619 2.03238 -1.01619 1.87696 -1.01619C1.75741 -1.01619 1.6259 -1.01619 1.51831 -0.968369Z" id="g3-122"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.25 0 0 1.25 0 0)">
<use x="38.8543" xlink:href="#g3-120" y="92.1544"/>
<use x="45.4815" xlink:href="#g0-48" y="87.2182"/>
<use x="51.5974" xlink:href="#g4-61" y="92.1544"/>
<use x="63.9889" xlink:href="#g3-120" y="92.1544"/>
<use x="70.6161" xlink:href="#g3-59" y="92.1544"/>
<use x="38.8543" xlink:href="#g3-121" y="109.589"/>
<use x="44.9696" xlink:href="#g0-48" y="104.653"/>
<use x="51.0855" xlink:href="#g4-61" y="109.589"/>
<use x="63.477" xlink:href="#g3-121" y="109.589"/>
<use x="72.249" xlink:href="#g4-43" y="109.589"/>
<use x="83.9763" xlink:href="#g4-40" y="109.589"/>
<use x="88.5116" xlink:href="#g3-121" y="109.589"/>
<use x="94.198" xlink:href="#g2-118" y="111.382"/>
<use x="101.762" xlink:href="#g1-0" y="109.589"/>
<use x="113.683" xlink:href="#g3-122" y="109.589"/>
<use x="119.633" xlink:href="#g4-41" y="109.589"/>
<use x="124.168" xlink:href="#g3-61" y="109.589"/>
<use x="129.999" xlink:href="#g4-52" y="109.589"/>
<use x="135.831" xlink:href="#g3-58" y="109.589"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,135 @@
// © Головин Г.Г., Код с комментариями, 2023
'use strict';
// Класс Точка трёхмерного пространства содержит методы для поворотов на угол и для получения проекций
// на плоскость. При получении проекций, вычисляется расстояние от точки до центра проекции. Точка также
// содержит статический метод для сравнения двух проекций точек.
class Point {
// координаты точки
constructor(x,y,z) {
this.x=x;
this.y=y;
this.z=z;
}
// поворачиваем эту точку на угол (deg)
// по осям (x,y,z) относительно точки (t0)
rotate(deg, t0) {
// функции для получения синуса и косинуса угла в радианах
const sin = (deg) => Math.sin((Math.PI/180)*deg);
const cos = (deg) => Math.cos((Math.PI/180)*deg);
// получаем новые координаты точки по формулам
// матрицы поворота для трёхмерного пространства
let x,y,z;
// поворот по оси 'x'
y = t0.y+(this.y-t0.y)*cos(deg.x)-(this.z-t0.z)*sin(deg.x);
z = t0.z+(this.y-t0.y)*sin(deg.x)+(this.z-t0.z)*cos(deg.x);
this.y=y; this.z=z;
// поворот по оси 'y'
x = t0.x+(this.x-t0.x)*cos(deg.y)-(this.z-t0.z)*sin(deg.y);
z = t0.z+(this.x-t0.x)*sin(deg.y)+(this.z-t0.z)*cos(deg.y);
this.x=x; this.z=z;
// поворот по оси 'z'
x = t0.x+(this.x-t0.x)*cos(deg.z)-(this.y-t0.y)*sin(deg.z);
y = t0.y+(this.x-t0.x)*sin(deg.z)+(this.y-t0.y)*cos(deg.z);
this.x=x; this.y=y;
}
// получаем проекцию типа (type) с расстояния (d)
// на плоскость экрана наблюдателя (tv)
projection(type, tv, d) {
let proj = {};
// получаем проекцию по экспериментальным формулам
switch (type) {
case 'parallel': {
proj.x = this.x;
proj.y = this.y+(tv.y-this.z)/4;
break;
}
case 'perspective': {
proj.x = tv.x+d*(this.x-tv.x)/(this.z-tv.z+d);
proj.y = tv.y+d*(this.y-tv.y)/(this.z-tv.z+d);
break;
}
}
// вычисляем расстояние до центра проекции
proj.dist = Math.sqrt((this.x-tv.x)*(this.x-tv.x)
+(this.y-tv.y)*(this.y-tv.y)
+(this.z-tv.z+d)*(this.z-tv.z+d));
return proj;
}
// сравниваем две проекции точек (p1,p2),
// координаты (x,y) должны совпадать
static pEquals(p1, p2) {
return Math.abs(p1.x-p2.x)<0.0001
&& Math.abs(p1.y-p2.y)<0.0001;
}
};
// Класс Куб содержит коллекцию вершин класса Точка и массив граней. Каждая грань — это массив из 4 вершин,
// выходящих из одной точки и идущих по часовой стрелке. Куб содержит методы для поворота всех вершин на угол
// и для получения проекций всех граней на плоскость. При получении проекций, вычисляется наклон грани — это
// удалённость от плоскости проекции. Куб также содержит два статических метода для сравнения двух проекций
// граней: для определения равноудалённых граней от центра проекции и смежных стенок между соседними кубиками.
class Cube {
// левая верхняя ближняя координата и размер
constructor(x,y,z,size) {
// правая нижняя дальняя координата
let xs=x+size,ys=y+size,zs=z+size;
let v={ // вершины
t000: new Point(x,y,z), // верх
t001: new Point(x,y,zs), // верх
t010: new Point(x,ys,z), // низ
t011: new Point(x,ys,zs), // низ
t100: new Point(xs,y,z), // верх
t101: new Point(xs,y,zs), // верх
t110: new Point(xs,ys,z), // низ
t111: new Point(xs,ys,zs)};// низ
this.vertices=v;
this.faces=[ // грани
[v.t000,v.t100,v.t110,v.t010], // передняя
[v.t000,v.t010,v.t011,v.t001], // левая
[v.t000,v.t001,v.t101,v.t100], // верхняя
[v.t001,v.t011,v.t111,v.t101], // задняя
[v.t100,v.t101,v.t111,v.t110], // правая
[v.t010,v.t110,v.t111,v.t011]];// нижняя
}
// поворачиваем вершины куба на угол (deg)
// по осям (x,y,z) относительно точки (t0)
rotate(deg, t0) {
for (let vertex in this.vertices)
this.vertices[vertex].rotate(deg, t0);
}
// получаем проекции типа (type) с расстояния (d)
// на плоскость экрана наблюдателя (tv)
projection(type, tv, d) {
let proj = [];
for (let face of this.faces) {
// проекция грани, массив вершин
let p = [];
// кумулятивная удалённость вершин
p.dist = 0;
// обходим вершины грани
for (let vertex of face) {
// получаем проекции вершин
let proj = vertex.projection(type, tv, d);
// накапливаем удалённость вершин
p.dist+=proj.dist;
// добавляем в массив вершин
p.push(proj);
}
// вычисляем наклон грани, удалённость от плоскости проекции
p.clock = ((p[1].x-p[0].x)*(p[2].y-p[0].y)
-(p[1].y-p[0].y)*(p[2].x-p[0].x))<0;
proj.push(p);
}
return proj;
}
// сравниваем две проекции граней (f1,f2), вершины
// должны быть равноудалены от центра проекции
static pEquidistant(f1, f2) {
return Math.abs(f1.dist-f2.dist)<0.0001;
}
// сравниваем две проекции граней (f1,f2), координаты
// точек по главной диагонали (p0,p2) должны совпадать
static pAdjacent(f1, f2) {
return Point.pEquals(f1[0],f2[0])
&& Point.pEquals(f1[2],f2[2]);
}
};

View file

@ -0,0 +1,57 @@
// © Головин Г.Г., Код с комментариями, 2023
'use strict';
// рисовать будем сразу две картинки,
// объект будет один, а проекций будет много
const canvas1 = document.getElementById('canvas1');
const canvas2 = document.getElementById('canvas2');
// создаём объект
const cube = new Cube(50,50,50,200);
// центр фигуры, вокруг него будем выполнять поворот
const t0 = new Point(150,150,150);
// удалённость центра проекции
const d = 300;
// положение экрана наблюдателя
const tv = new Point(150,150,80);
// угол поворота в градусах
const deg = {x:0,y:1,z:0};
// поворот фигуры и обновление изображения
function repaint() {
cube.rotate(deg, t0);
// рисуем параллельную проекцию
drawFigure(canvas1, cube.projection('parallel', tv));
// рисуем перспективную проекцию
drawFigure(canvas2, cube.projection('perspective', tv, d));
}
// рисуем фигуру по точкам из массива
function drawFigure(canvas, proj) {
let context = canvas.getContext('2d');
// сортируем грани по их наклону
proj.sort((a,b) => b.clock-a.clock);
// очищаем весь холст целиком
context.clearRect(0, 0, canvas.width, canvas.height);
// обходим массив граней куба
for (let i = 0; i < proj.length; i++) {
// обходим массив точек и соединяем их линиями
context.beginPath();
for (let j = 0; j < proj[i].length; j++) {
if (j == 0) {
context.moveTo(proj[i][j].x, proj[i][j].y);
} else {
context.lineTo(proj[i][j].x, proj[i][j].y);
}
}
context.closePath();
// рисуем грань куба вместе с рёбрами
context.lineWidth = 2.2;
context.lineJoin = 'round';
context.fillStyle = '#fff9';
context.strokeStyle = '#222';
context.fill();
context.stroke();
}
}
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));

View file

@ -0,0 +1,55 @@
// © Головин Г.Г., Экспериментальная модель, 2023
'use strict';
let d3=300,tv3={x:150,y:150,z:60};
let deg2={x:1,y:1,z:1},show=false;
// обработчики событий в форме
function changeAxis(val,caller) {
deg2[val]=0+caller.target.checked;
}
function changeDistance(caller) {
d3=caller.target.valueAsNumber;
}
function changeTv(val,caller) {
tv3[val]=caller.target.valueAsNumber;
}
function showCenter(caller) {
show=caller.target.checked;
}
const cube3 = new Cube(50,50,50,200);
const canvas3 = document.getElementById('canvas3');
// перетаскивание центральной точки мышью
let msBtnPressed = false;
canvas3.onmouseup = ()=> msBtnPressed=false;
canvas3.onmousedown = (caller)=> {
msBtnPressed=true;
canvas3.onmousemove(caller);
}
canvas3.onmousemove = function(caller) {
if (msBtnPressed && show) {
tv3.x=caller.offsetX;
tv3.y=caller.offsetY;
document.getElementById('rangeX').value=caller.offsetX;
document.getElementById('resultX').value=caller.offsetX;
document.getElementById('rangeY').value=caller.offsetY;
document.getElementById('resultY').value=caller.offsetY;
}
}
// поворот фигуры и обновление изображения
function repaint3() {
cube3.rotate(deg2, t0);
// рисуем перспективную проекцию
drawFigure(canvas3, cube3.projection('perspective', tv3, d3));
// центральная точка перспективной проекции
if (show) centerPoint(canvas3);
}
// центральная точка перспективной проекции
function centerPoint(canvas) {
const context = canvas.getContext('2d');
context.beginPath();
context.lineWidth = 2.2;
context.strokeStyle = '#222';
context.arc(tv3.x, tv3.y, 5.5, 0, 2*Math.PI);
context.stroke();
}
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint3,50));

View file

@ -0,0 +1,116 @@
// © Головин Г.Г., Код с комментариями, 2023
'use strict';
// матрицы-шаблоны для кубиков
const shape1 = [ // пространственный крест
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]];
const shape2 = [ // крест-куб
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]],
[[0,0,1,0,0], [0,0,0,0,0], [1,0,0,0,1], [0,0,0,0,0], [0,0,1,0,0]],
[[1,1,1,1,1], [1,0,0,0,1], [1,0,0,0,1], [1,0,0,0,1], [1,1,1,1,1]],
[[0,0,1,0,0], [0,0,0,0,0], [1,0,0,0,1], [0,0,0,0,0], [0,0,1,0,0]],
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]]];
// размер кубика, количество кубиков в ряду, отступ
const size = 40, row = 5, gap = 50;
// массивы для кубиков
const cubes1 = [], cubes2 = [];
// обходим матрицы, заполняем массивы кубиками
for (let x=0; x<row; x++)
for (let y=0; y<row; y++)
for (let z=0; z<row; z++) {
if (shape1[x][y][z]==1)
cubes1.push(new Cube(x*size+gap,y*size+gap,z*size+gap,size));
if (shape2[x][y][z]==1)
cubes2.push(new Cube(x*size+gap,y*size+gap,z*size+gap,size));
}
// центр фигуры, вокруг него будем выполнять поворот
const t0 = new Point(150,150,150);
// удалённость центра проекции
const d = 300;
// положение экрана наблюдателя
const tv = new Point(150,150,125);
// угол поворота в градусах
const deg = {x:1,y:1,z:1};
// рисовать будем по две картинки для каждой фигуры
const canvas1 = document.getElementById('canvas1');
const canvas2 = document.getElementById('canvas2');
const canvas3 = document.getElementById('canvas3');
const canvas4 = document.getElementById('canvas4');
// обновление изображения
function repaint() {
// пространственный крест
processFigure(cubes1,canvas1,canvas2);
// крест-куб
processFigure(cubes2,canvas3,canvas4);
}
// поворачиваем фигуру и получаем проекции
function processFigure(cubes,cnv1,cnv2) {
// массивы проекций граней кубиков
let parallel = [], perspective = [];
// поворачиваем кубики и получаем проекции
for (let cube of cubes) {
cube.rotate(deg, t0);
parallel = parallel.concat(cube.projection('parallel',tv,d));
perspective = perspective.concat(cube.projection('perspective',tv,d));
}
// смежные стенки между соседними кубиками не рисуем
noAdjacent(parallel);
noAdjacent(perspective);
// сортируем грани разных кубиков по удалённости и внутри одного кубика по наклону
parallel.sort((a,b)=>Math.abs(b.dist-a.dist)>size ? b.dist-a.dist : b.clock-a.clock);
// сортируем грани по удалённости от центра проекции
perspective.sort((a,b)=>b.dist-a.dist);
// рисуем параллельную проекцию
drawFigure(cnv1, parallel);
// рисуем перспективную проекцию
drawFigure(cnv2, perspective);
}
// смежные стенки между соседними кубиками не рисуем
function noAdjacent(array) {
// сортируем грани по удалённости
array.sort((a,b) => b.dist-a.dist);
// удаляем смежные стенки между кубиками
for (let i=0, j=1; i<array.length-1; j=++i+1)
while (j<array.length && Cube.pEquidistant(array[i],array[j]))
if (Cube.pAdjacent(array[i],array[j])) {
array.splice(j,1);
array.splice(i,1);
i--; j=array.length;
} else j++;
}
// рисуем фигуру по точкам из массива
function drawFigure(canvas, proj, alpha=0.8) {
const context = canvas.getContext('2d');
// очищаем весь холст целиком
context.clearRect(0, 0, canvas.width, canvas.height);
// обходим массив граней куба
for (let i = 0; i < proj.length; i++) {
// обходим массив точек и соединяем их линиями
context.beginPath();
for (let j = 0; j < proj[i].length; j++) {
if (j == 0) {
context.moveTo(proj[i][j].x, proj[i][j].y);
} else {
context.lineTo(proj[i][j].x, proj[i][j].y);
}
}
context.closePath();
// рисуем грань куба вместе с рёбрами
context.lineWidth = 1.9;
context.lineJoin = 'round';
context.fillStyle = 'rgba(200,230,201,'+alpha+')';
context.strokeStyle = 'rgba(102,187,106,'+(0.2+alpha)+')';
context.fill();
context.stroke();
}
}
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));

View file

@ -0,0 +1,96 @@
// © Головин Г.Г., Экспериментальная модель, 2023
'use strict';
let d5=300,tv5={x:150,y:150,z:125},show=false;
let deg2={x:1,y:1,z:1};
let sortOrder=true,alpha=20,first=false;
// обработчики событий в форме
function changeAxis(val,caller) {
deg2[val]=0+caller.target.checked;
}
function changeDistance(caller) {
d5=caller.target.valueAsNumber;
}
function changeTv(val,caller) {
tv5[val]=caller.target.valueAsNumber;
}
function showCenter(caller) {
show=caller.target.checked;
}
function changeFigure(caller) {
if (caller.target.value=="first") first=true;
if (caller.target.value=="second") first=false;
}
function changeOrder(caller) {
if (caller.target.value=="linear") sortOrder=true;
if (caller.target.value=="reverse") sortOrder=false;
}
function changeAlpha(caller) {
alpha=caller.target.valueAsNumber;
}
const canvas5 = document.getElementById('canvas5');
// перетаскивание центральной точки мышью
let msBtnPressed = false;
canvas5.onmouseup = ()=> msBtnPressed=false;
canvas5.onmousedown = (caller)=> {
msBtnPressed=true;
canvas5.onmousemove(caller);
}
canvas5.onmousemove = (caller)=> {
if (msBtnPressed && show) {
tv5.x=caller.offsetX;
tv5.y=caller.offsetY;
document.getElementById('rangeX').value=caller.offsetX;
document.getElementById('resultX').value=caller.offsetX;
document.getElementById('rangeY').value=caller.offsetY;
document.getElementById('resultY').value=caller.offsetY;
}
}
// массивы для кубиков
const cubes5a = [], cubes5b = [];
// обходим матрицы, заполняем массивы кубиками
for (let x=0; x<row; x++)
for (let y=0; y<row; y++)
for (let z=0; z<row; z++) {
if (shape1[x][y][z]==1)
cubes5a.push(new Cube(x*size+gap,y*size+gap,z*size+gap,size));
if (shape2[x][y][z]==1)
cubes5b.push(new Cube(x*size+gap,y*size+gap,z*size+gap,size));
}
// поворот фигуры и обновление изображения
function repaint5() {
if (first) // пространственный крест
processFigure5(cubes5a,canvas5);
else // крест-куб
processFigure5(cubes5b,canvas5);
}
// поворачиваем фигуру и получаем проекции
function processFigure5(cubes,canvas) {
// массив проекций граней кубиков
let proj = [];
// поворачиваем кубики и получаем проекции
for (let cube of cubes) {
cube.rotate(deg2, t0);
proj = proj.concat(cube.projection('perspective',tv5,d5));
}
// смежные стенки между соседними кубиками не рисуем
noAdjacent(proj);
// сортируем грани по удалённости
proj.sort((a,b)=>b.dist-a.dist);
// сортировка в обратном порядке
if (!sortOrder) proj.reverse();
// рисуем перспективную проекцию
drawFigure(canvas, proj, (100-alpha)/100);
// центральная точка перспективной проекции
if (show) centerPoint(canvas);
}
// центральная точка перспективной проекции
function centerPoint(canvas) {
const context = canvas.getContext('2d');
context.beginPath();
context.lineWidth = 3.2;
context.strokeStyle = '#66bb6a';
context.arc(tv5.x, tv5.y, 6.5, 0, 2*Math.PI);
context.stroke();
}
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint5,50));

View file

@ -0,0 +1,52 @@
// © Головин Г.Г., Код с комментариями, 2023
'use strict';
let canvas = document.getElementById('canvas');
// исходный массив точек-вершин квадрата
let square = [{x:50,y:50},{x:50,y:250},{x:250,y:250},{x:250,y:50}];
// центр фигуры, вокруг него будем выполнять поворот
let t0 = {x:150, y:150};
// угол поворота в градусах
let deg = 1;
// поворот фигуры и обновление изображения
function repaint() {
// поворачиваем исходный массив точек на угол
for (let i = 0; i < square.length; i++)
square[i] = rotateOnDegree(t0, square[i], deg);
// рисуем текущий массив точек
drawFigure(canvas, square);
}
// поворачиваем точку (t) на угол (deg) относительно точки (t0)
function rotateOnDegree(t0, t, deg) {
let t_new = {};
// переводим угол поворота из градусов в радианы
let rad = (Math.PI / 180) * deg;
// рассчитываем координаты новой точки по формуле
t_new.x = t0.x+(t.x-t0.x)*Math.cos(rad)-(t.y-t0.y)*Math.sin(rad);
t_new.y = t0.y+(t.x-t0.x)*Math.sin(rad)+(t.y-t0.y)*Math.cos(rad);
// возвращаем новую точку
return t_new;
}
// рисуем фигуру по точкам из массива
function drawFigure(canvas, arr) {
let context = canvas.getContext('2d');
// очищаем весь холст целиком
context.clearRect(0, 0, canvas.width, canvas.height);
// обходим массив точек и соединяем их линиями
context.beginPath();
for (let i = 0; i < arr.length; i++)
if (i == 0)
context.moveTo(arr[i].x, arr[i].y);
else
context.lineTo(arr[i].x, arr[i].y);
context.closePath();
// рисуем линии на холсте
context.lineWidth = 2.2;
context.strokeStyle = '#222';
context.stroke();
}
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));

View file

@ -0,0 +1,26 @@
// © Головин Г.Г., Код с комментариями, 2023
'use strict';
let canvas2 = document.getElementById('canvas2');
// текущий массив точек
let square2 = [];
// вращающаяся точка
let t2 = {x:100, y:100};
// поворот фигуры и обновление изображения
function repaint2() {
// поворачиваем точку в обратную сторону
t2 = rotateOnDegree(t0, t2, -deg);
// обходим точки исходного массива и сдвигаем
for (let i = 0; i < square.length; i++) {
// текущая точка
square2[i] = {};
// сдвигаем точку исходного массива
square2[i].x = square[i].x - t0.x + t2.x;
square2[i].y = square[i].y - t0.y + t2.y;
}
// рисуем текущий массив точек
drawFigure(canvas2, square2);
}
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint2,50));

View file

@ -0,0 +1,177 @@
// © Головин Г.Г., Обработка действий пользователя, 2023
'use strict';
// коды кнопок на клавиатуре
const KEY = {PAUSE:19,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40};
// типы объёмного изображения
const VOLUME = {FLAT:0,PARALLEL:1,PERSPECTIVE:2};
// текущий тип изображения
let vol = VOLUME.FLAT;
// кнопка нажата и удерживается
function keyPressed(caller) {
if (status == GAME.OVER) return;
switch (caller.keyCode) {
case KEY.PAUSE: {
status = GAME.PAUSE;
statusView.refresh();
return;
}
case KEY.LEFT: {
caller.preventDefault();
moveFigureLeft();
break;
}
case KEY.RIGHT: {
caller.preventDefault();
moveFigureRight();
break;
}
case KEY.SPACE:
case KEY.UP: {
caller.preventDefault();
rotateFigure();
break;
}
case KEY.DOWN: {
caller.preventDefault();
rapidFall = true;
if (sleepTimeout != undefined) {
clearTimeout(sleepTimeout);
stepDown();
}
break;
}
default: {
break;
}
}
if (status == GAME.LEVEL || status == GAME.PAUSE) {
status = GAME.RUN;
setTimeout(figureFall, 60);
}
}
// кнопка отпущена
function keyReleased(caller) {
if (caller.keyCode == KEY.DOWN) {
rapidFall = false;
}
}
// изменить количество строк
function changeRows(caller) {
rows = caller.target.valueAsNumber;
container.changeSize();
t0.reCalc();
tv2.reCalc();
refreshParams();
prepareNewGame();
}
// изменить количество колонок
function changeColumns(caller) {
columns = caller.target.valueAsNumber;
container.changeSize();
t0.reCalc();
tv2.reCalc();
refreshParams();
prepareNewGame();
}
// переключить режим улитки
function changeSnailMode(caller) {
if (caller.target.checked)
reduction=REDUCTION_SNAIL;
else
reduction=REDUCTION_STEP;
}
// изменить тип объёмного изображения
function changeVolume(caller) {
const value = caller.target.value;
const old = vol;
if (value=="off") vol=VOLUME.FLAT;
if (value=="parallel") vol=VOLUME.PARALLEL;
if (value=="perspective") vol=VOLUME.PERSPECTIVE;
refreshDisabled();
repaint(false);
}
// изменяем прозрачность фигур
function changeAlpha(caller) {
colors.alpha=caller.target.valueAsNumber;
}
// поворачиваем кубики, изменяем текущий угол
function rotate(axis, caller) {
deg[axis] = caller.target.valueAsNumber;
prepare3D();
}
// вертикальная корректировка
function changeTv1(caller) {
tv1.y = caller.target.valueAsNumber;
}
// центральная точка на экране наблюдателя
function changeTv2(axis, caller) {
tv2[axis] = caller.target.valueAsNumber;
}
// удалённость источника проекции
function changeDistance2(caller) {
d2=caller.target.valueAsNumber;
}
// показать центральную точку
function showCenter(caller) {
tv2.show=!tv2.show;
}
// обновить игру и все настройки
function reload() {
vol=VOLUME.FLAT;
field3D=[];
colors.setDefault();
deg.setDefault();
tv1.reCalc();
tv2.reCalc();
reduction=REDUCTION_STEP;
prepareNewGame();
refreshParams();
}
// обновить отображение параметров
function refreshParams() {
document.getElementById('speedometer').value=0;
document.getElementById('snail').checked=(reduction==REDUCTION_SNAIL);
document.getElementById('alpha').value=colors.alpha;
document.getElementById('oAlpha').value=colors.alpha + '%';
document.getElementById('off').checked=(vol==VOLUME.FLAT);
document.getElementById('parallel').checked=(vol==VOLUME.PARALLEL);
document.getElementById('perspective').checked=(vol==VOLUME.PERSPECTIVE);
document.getElementById('rotateX').value = deg.x;
document.getElementById('rotateXo').value = deg.x + '°';
document.getElementById('rotateY').value = deg.y;
document.getElementById('rotateYo').value = deg.y + '°';
document.getElementById('rotateZ').value = deg.z;
document.getElementById('rotateZo').value = deg.z + '°';
document.getElementById('tv1Y').value = tv1.y;
document.getElementById('tv1Yo').value = tv1.y;
document.getElementById('center').checked = tv2.show;
document.getElementById('tv2X').max = container.canvas.width;
document.getElementById('tv2X').value = tv2.x;
document.getElementById('tv2Xo').value = tv2.x;
document.getElementById('tv2Y').max = container.canvas.height;
document.getElementById('tv2Y').value = tv2.y;
document.getElementById('tv2Yo').value = tv2.y;
document.getElementById('tv2Z').max = d2/2;
document.getElementById('tv2Z').value = tv2.z;
document.getElementById('tv2Zo').value = tv2.z;
document.getElementById('dist').max = d2*2;
document.getElementById('dist').value = d2;
document.getElementById('oDist').value = d2;
refreshDisabled();
}
// обновить доступность блоков
function refreshDisabled() {
document.getElementById('rotateX').disabled=(vol==VOLUME.FLAT);
document.getElementById('rotateY').disabled=(vol==VOLUME.FLAT);
document.getElementById('rotateZ').disabled=(vol==VOLUME.FLAT);
document.getElementById('tv1Y').disabled=(vol!=VOLUME.PARALLEL);
document.getElementById('center').disabled=(vol!=VOLUME.PERSPECTIVE);
document.getElementById('tv2X').disabled=(vol!=VOLUME.PERSPECTIVE);
document.getElementById('tv2Y').disabled=(vol!=VOLUME.PERSPECTIVE);
document.getElementById('tv2Z').disabled=(vol!=VOLUME.PERSPECTIVE);
document.getElementById('dist').disabled=(vol!=VOLUME.PERSPECTIVE);
}
// после загрузки всех частей страницы
document.addEventListener('DOMContentLoaded', function() {
refreshParams();
});

View file

@ -0,0 +1,42 @@
// © Головин Г.Г., Набор фигур, 2023
'use strict';
// фигуры тетрамино
const FIGURE=[
[[1,1],[1,0],[1,0]],
[[2,2],[0,2],[0,2]],
[[0,3],[3,3],[3,0]],
[[4,0],[4,4],[0,4]],
[[5,5],[5,5]],
[[6],[6],[6],[6]],
[[7,0],[7,7],[7,0]]];
// полный набор фигур
FIGURE.set = function() {
let set = [];
for (let i=0; i<FIGURE.length; i++)
set.push(new Figure(i));
return set;
}
// класс-фабрика для фигур
class Figure {
// создать новый объект
constructor(num) {
// num - номер в диапазоне [0..6]
if (num<0||num>6) return undefined;
this.type=num+1;
this.shape=FIGURE[num];
}
// копия текущего объекта
clone() {
return new Figure(this.type-1);
}
// поворот по часовой стрелке
rotate() {
let nShape = [], shape = this.shape;
for (let y = 0; y < shape.length; y++)
for (let x = 0; x < shape[y].length; x++) {
if (nShape[x]==undefined) nShape[x] = [];
nShape[x][shape.length-y-1] = shape[y][x];
}
this.shape=nShape;
}
};

View file

@ -0,0 +1,245 @@
// © Головин Г.Г., Логика игрового процесса, 2023
'use strict';
// игровое поле и его размеры
let field, rows = 20, columns = 10;
// ускорение падения фигур
const REDUCTION_STEP = 25;
const REDUCTION_SNAIL = 5;
let reduction = REDUCTION_STEP;
// скорость падения фигур
const START_DELAY = 600;
const MIN_DELAY = 80;
let stepDelay = START_DELAY;
let sleepTimeout, rapidFall = false;
// уровень, следующий уровень, счёт
let level, nextLevel, score;
// массив фигур тетрамино
const figures = FIGURE.set();
// текущая фигура, следующая фигура
let currentFigure, nextFigure;
// статусы игры
const GAME = {RUN:0,LEVEL:1,PAUSE:2,OVER:3};
// текущий статус
let status = GAME.PAUSE;
// подготовить новую игру
function prepareNewGame() {
field = [];
for (let i = 0; i < rows; i++) {
field[i] = [];
for (let j = 0; j < columns; j++)
field[i][j] = 0;
}
status = GAME.PAUSE;
level = 0;
score = 0;
nextLevel = (10 * columns) * (level + 1);
stepDelay = START_DELAY;
startFigureFall();
repaint();
}
// начало падения фигуры
function startFigureFall() {
currentFigure = nextFigure;
const x = Math.floor(columns/2+columns%2-1);
if (isFreeSpace(0, x)) {
doPlaceFigure(0, x);
repaint();
} else {
status=GAME.OVER;
for (let y=-1; y>-4; y--)
if (isFreeSpace(y, x, false)) {
doPlaceFigure(y, x);
break;
}
repaint();
return;
}
const rnd = Math.floor(Math.random() * figures.length);
nextFigure = figures[rnd].clone();
if (status==GAME.LEVEL) return;
setTimeout(figureFall, 60);
}
// падение фигуры
function figureFall() {
if (rapidFall)
stepDown();
else
sleepTimeout = setTimeout(stepDown, stepDelay);
}
// шаг вниз
function stepDown() {
sleepTimeout = undefined;
if (status==GAME.PAUSE) return;
if (isSpaceDown()) {
doStepDown();
setTimeout(figureFall, 60);
} else {
mergeFigure(currentFigure.type);
let fullRows = 0;
for (let i = 0; i < rows; i++)
if (isFullRow(i)) {
for (let c = 3; c >= 0; c--)
setTimeout(blinkFullRow, 400 * fullRows + 100 * c, i, c);
setTimeout(slideDown, 400 * fullRows + 400, i);
fullRows++;
}
score += columns * [0,1,3,5,10][fullRows];
if (score >= nextLevel) {
level++;
status = GAME.LEVEL;
nextLevel = (10 * columns) * (level + 1);
stepDelay = Math.max(MIN_DELAY,stepDelay-reduction);
}
startFigureFall();
}
}
// свободное место ниже текущей фигуры
function isSpaceDown() {
for (let y = rows-2; y >= 0; y--)
for (let x = 0; x < columns; x++)
if (field[y][x]==11 && field[y+1][x]>0 && field[y+1][x]<11
|| field[y+1][x]==11 && y==rows-2)
return false;
return true;
}
// сдвинуть текущую фигуру вниз
function doStepDown() {
for (let y = rows-2; y >= 0; y--)
for (let x = 0; x < columns; x++)
if (field[y][x]==11) {
field[y][x]=0;
field[y+1][x]=11;
}
repaint();
}
// завершение движения текущей фигуры
function mergeFigure(type) {
for (let x = 0; x < columns; x++)
for (let y = 0; y < rows; y++)
if (field[y][x] == 11)
field[y][x] = type;
}
// заполненная строка
function isFullRow(row) {
for (let x = 0; x < columns; x++)
if (field[row][x] == 0)
return false;
return true;
}
// моргание заполненной строки
function blinkFullRow(row, color) {
for (let x = 0; x < columns; x++)
field[row][x] = color;
repaint();
}
// сдвинуть поле вниз
function slideDown(row) {
for (let y = row-1; y >= 0; y--)
for (let x = 0; x < columns; x++)
if (field[y+1][x]!=11 && field[y][x]!=11)
field[y+1][x]=field[y][x];
repaint();
}
// свободное место для текущей фигуры в пределах границ поля
function isFreeSpace(y, x, fullSize=true) {
const height = currentFigure.shape.length;
const wight = currentFigure.shape[0].length;
if (fullSize && (y<0 || y+height>rows || x<0 || x+wight>columns))
return false;
for (let yy=0; yy<height; yy++)
for (let xx=0; xx<wight; xx++)
if (currentFigure.shape[yy][xx]>0)
if (y+yy>=0 && y+yy<rows && x+xx>=0 && x+xx<columns)
if (field[y+yy][x+xx]!=0)
return false;
return true;
}
// разместить текущую фигуру в пределах границ поля
function doPlaceFigure(y, x, type=11) {
const height = currentFigure.shape.length;
const wight = currentFigure.shape[0].length;
for (let yy=0; yy<height; yy++)
for (let xx=0; xx<wight; xx++)
if (currentFigure.shape[yy][xx]>0)
if (y+yy>=0 && y+yy<rows && x+xx>=0 && x+xx<columns)
field[y+yy][x+xx]=type;
}
// для вызова из контроллера
function moveFigureLeft() {
if (isSpaceLeft())
doStepLeft();
repaint();
}
// свободное место слева от текущей фигуры
function isSpaceLeft() {
for (let x = 1; x < columns; x++)
for (let y = 0; y < rows; y++)
if (field[y][x]==11 && field[y][x-1]>0 && field[y][x-1]<11
|| field[y][x-1]==11 && x==1)
return false;
return true;
}
// сдвинуть текущую фигуру влево
function doStepLeft() {
for (let x = 1; x < columns; x++)
for (let y = 0; y < rows; y++)
if (field[y][x]==11) {
field[y][x]=0;
field[y][x-1]=11;
}
}
// для вызова из контроллера
function moveFigureRight() {
if (isSpaceRight())
doStepRight();
repaint();
}
// свободное место справа от текущей фигуры
function isSpaceRight() {
for (let x = columns-2; x >=0; x--)
for (let y = 0; y < rows; y++)
if (field[y][x]==11 && field[y][x+1]>0 && field[y][x+1]<11
|| field[y][x+1]==11 && x==columns-2)
return false;
return true;
}
// сдвинуть текущую фигуру вправо
function doStepRight() {
for (let x = columns-2; x >=0; x--)
for (let y = 0; y < rows; y++)
if (field[y][x]==11) {
field[y][x]=0;
field[y][x+1]=11;
}
}
// для вызова из контроллера, поворот фигуры
function rotateFigure() {
let y = rows, x = columns;
for (let yy = 0; yy < rows; yy++)
for (let xx = 0; xx < columns; xx++)
if (field[yy][xx] == 11) {
if (y > yy) y = yy;
if (x > xx) x = xx;
}
if (y == rows || x == columns) return;
const old = currentFigure.shape;
doPlaceFigure(y, x, 0);
currentFigure.rotate();
if (isFreeSpace(y, x))
doPlaceFigure(y, x);
else if (isFreeSpace(y, x-1))
doPlaceFigure(y, x-1);
else {
currentFigure.shape = old;
doPlaceFigure(y, x);
}
repaint();
}
// после загрузки всех частей страницы, запускаем игру
document.addEventListener('DOMContentLoaded', function() {
addEventListener('keydown', keyPressed);
addEventListener('keyup', keyReleased);
const rnd = Math.floor(Math.random() * figures.length);
nextFigure = figures[rnd].clone();
prepareNewGame();
});

View file

@ -0,0 +1,235 @@
// © Головин Г.Г., Визуализация игрового процесса, 2023
'use strict';
// размер клеточки, отступ
const size = 30, gap = 2;
// массив статусов игры
const statuses = ["ИГРА","УРОВЕНЬ","ПАУЗА","ЗАВЕРШЕНО"];
// массив цветов для фигур
const colors = [
'rgba(240,240,240,1)',
'rgba(150,0,0,1)',
'rgba(0,0,150,1)',
'rgba(150,150,0,1)',
'rgba(0,150,150,1)',
'rgba(0,150,0,1)',
'rgba(150,0,150,1)',
'rgba(150,80,80,1)'];
// прозрачность фигур
colors.setDefault = function() {
this.alpha = 0;
}
colors.setDefault();
// получаем цвет, добавляем прозрачность только фигурам
colors.get = function(...numbers) {
for (let num of numbers)
if (num <= 0) return this[0];
else if (num < colors.length)
return this[num].replace('1)', (100-this.alpha)/100 + ')');
return this[0];
}
// массив для кубиков
let field3D = [];
// центральная точка для поворотов
const t0 = {}; t0.reCalc = function() {
this.x = columns*(size+gap)/2;
this.y = rows*(size+gap);
this.z = (size+gap)*2;
};
t0.reCalc();
// угол поворота игрового поля с кубиками
let deg={}; deg.setDefault = function() {
this.x=-1;
this.y=0;
this.z=0;
};
deg.setDefault();
// параллельная проекция: центр и экран наблюдателя
let d1 = 600, tv1={}; tv1.reCalc = function() {
this.x=columns*(size+gap)/2;
this.y=(size+gap)*2;
this.z=(size+gap)*2;
d1 = Math.max(rows,columns)*(size+gap);
}
tv1.reCalc();
// перспективная проекция: центр и экран наблюдателя
let d2 = 600, tv2 = {}; tv2.reCalc = function() {
this.x = columns*(size+gap)/2;
this.y = rows*(size+gap)/2;
this.z = (size+gap)*2;
this.show=false;
d2 = Math.max(rows,columns)*(size+gap);
};
tv2.reCalc();
// стакан с игрой
const container = {};
container.canvas = document.getElementById('container');
container.context = container.canvas.getContext('2d');
container.changeSize = function() {
this.canvas.width = columns*size+(columns+1)*gap;
this.canvas.height = rows*size+(rows+1)*gap;
};
container.changeSize();
// перетаскивание центральной точки мышью
container.msBtnPressed = false;
container.canvas.onmouseup = ()=> container.msBtnPressed=false;
container.canvas.onmousedown = (caller)=> {
container.msBtnPressed=true;
container.canvas.onmousemove(caller);
}
container.canvas.onmousemove = (caller)=> {
if (vol==VOLUME.PERSPECTIVE && container.msBtnPressed && tv2.show) {
tv2.x = caller.offsetX;
tv2.y = caller.offsetY;
repaint(false);
refreshParams();
}
}
// следующая фигура
const next = {};
next.canvas = document.getElementById('next');
next.context = next.canvas.getContext('2d');
next.changeSize = function() {
this.canvas.width = 2*size+3*gap;
this.canvas.height = 4*size+5*gap;
};
next.changeSize();
// состояние игры
const statusView = {};
statusView.level = document.getElementById('levelView');
statusView.score = document.getElementById('scoreView');
statusView.nextLevel = document.getElementById('nextLevelView');
statusView.speed = document.getElementById('speedometer')
statusView.status = document.getElementById('statusView');
statusView.refresh = function() {
this.level.innerText = level;
this.score.innerText = score;
this.nextLevel.innerText = nextLevel;
this.speed.value = speedometer();
this.status.innerText = statuses[status];
}
// обновление изображения
function repaint(refresh3D=true) {
// состояние игры
statusView.refresh();
// стакан с игрой
if (vol==VOLUME.FLAT) {
drawCells(container.canvas, container.context, field, currentFigure.type);
} else {
if (refresh3D || field3D.length==0)
prepare3D();
repaint3D();
}
// следующая фигура
drawCells(next.canvas, next.context, nextFigure.shape);
}
// рисуем массив клеточек
function drawCells(canvas, context, array, color) {
// очищаем весь холст целиком
context.clearRect(0, 0, canvas.width, canvas.height);
// обходим массив, рисуем клеточки
for (let y=0; y<array.length; y++)
for (let x=0; x<array[y].length; x++) {
context.fillStyle = colors.get(array[y][x], color);
context.fillRect(gap+x*(size+gap), gap+y*(size+gap), size, size);
}
}
// обходим поле, создаём кубики
function prepare3D() {
field3D = [];
for (let y=0; y<field.length; y++)
for (let x=0; x<field[y].length; x++) {
let cube = new Cube(gap+x*(size+gap),gap+y*(size+gap),size+gap,size+gap);
// в пустых кубиках оставляем только заднюю стенку
if (field[y][x] == 0) {
for (let i=0;i<3;i++) cube.faces.shift();
for (let i=0;i<2;i++) cube.faces.pop();
}
cube.rotate(deg, t0);
cube.color = field[y][x] < 11 ? field[y][x] : currentFigure.type;
field3D.push(cube);
}
}
// рисуем массив кубиков
function repaint3D() {
// проекции граней кубиков
let proj = [];
// получаем массив проекций
for (let cube of field3D) {
let cProj;
if (vol==VOLUME.PARALLEL)
cProj = cube.projection('parallel',tv1,d1);
else
cProj = cube.projection('perspective',tv2,d2);
for (let face of cProj)
face.color = cube.color;
proj = proj.concat(cProj);
}
// сортируем грани по удалённости от центра проекции
proj.sort((a,b) => b.dist-a.dist);
// удаляем смежные стенки между соседними кубиками
for (let i=0, j=1; i<proj.length-1; j=++i+1)
while (j<proj.length && Cube.pEquidistant(proj[i],proj[j]))
if (Cube.pAdjacent(proj[i],proj[j])) {
proj.splice(j,1);
proj.splice(i,1);
i--; j=proj.length;
} else j++;
if (vol==VOLUME.PARALLEL)
// сортируем грани разных кубиков по удалённости и внутри одного кубика по наклону
proj.sort((a,b)=>Math.abs(b.dist-a.dist)>size ? b.dist-a.dist : b.clock-a.clock);
// обновляем стакан с игрой
drawCubes(container.canvas, container.context, proj);
// центральная точка перспективной проекции
if (vol==VOLUME.PERSPECTIVE && tv2.show) centerPoint(container.context);
}
// обходим массив, рисуем грани по точкам
function drawCubes(canvas, context, array) {
// очищаем весь холст целиком
context.clearRect(0, 0, canvas.width, canvas.height);
// рисуем только видимые грани
const visible = function(face) {
// если есть хотя бы одна точка, которую можно нарисовать
for (let j = 0; j < face.length; j++)
if (face[j].x>-size && face[j].x<canvas.width+size
&& face[j].y>-size && face[j].y<canvas.height+size)
return true;
return false;
};
// обходим массив граней куба
for (let i = 0; i < array.length; i++) {
// рисуем только видимые грани
if (!visible(array[i])) continue;
// обходим массив точек и соединяем их линиями
context.beginPath();
for (let j = 0; j < array[i].length; j++)
if (j==0) context.moveTo(array[i][j].x, array[i][j].y);
else context.lineTo(array[i][j].x, array[i][j].y);
context.closePath();
// рисуем линии на холсте
context.lineWidth = 1.7;
context.lineJoin = 'round';
context.fillStyle = colors.get(array[i].color);
context.strokeStyle = '#ffff';
context.fill();
context.stroke();
}
}
// центральная точка перспективной проекции
function centerPoint(context) {
context.beginPath();
context.lineWidth = 3.2;
context.strokeStyle = '#66bb6a';
context.arc(tv2.x, tv2.y, 6.5, 0, 2*Math.PI);
context.stroke();
}
// скорость падения фигуры
const speedometer = function() {
let speed = 0;
return function() {
if (rapidFall)
speed = Math.min(START_DELAY, speed + 80);
else
speed = Math.max(0, speed - 80);
return Math.max(speed, START_DELAY - stepDelay);
}
}();

7
jekyll_site/robots.txt Normal file
View file

@ -0,0 +1,7 @@
User-agent: *
Disallow: *404*
Sitemap: https://pomodoro1.mircloud.ru/pagesmap.xml
Sitemap: https://pomodoro1.mircloud.ru/color/pagesmap.xml
Host: https://pomodoro1.mircloud.ru

View file

@ -0,0 +1,160 @@
---
title: Вращаем квадрат на плоскости
description: Напишем алгоритм на JavaScript для поворота квадрата на угол вокруг своего центра, повторим программу средней школы. Для расчётов будем использовать класс...
sections: [Линейная алгебра,Матрица поворота]
tags: [javascript,canvas,геометрия,графика,изображение,картинка,квадрат]
scripts: [/js/spinning-square.js,/js/spinning-square2.js]
canonical_url: /ru/2023/01/05/spinning-square-on-plane.html
url_translated: /en/2023/01/06/spinning-square-on-plane.html
title_translated: Spinning square on plane
date: 2023.01.05
---
Напишем алгоритм на JavaScript для поворота квадрата на угол вокруг своего центра, повторим программу
средней школы. Для расчётов будем использовать класс `Math`, а для отображения результатов Canvas.
Развитие мысли, объёмная модель: [Вращаем куб в пространстве]({{ '/ru/2023/01/10/spinning-cube-in-space.html' | relative_url }}).
### Поворот точки на плоскости {#point-rotation-on-plane}
Рассчитываем координаты новой точки по формулам матрицы поворота для двухмерного пространства.
Поворачиваем точку `t` относительно точки `t0` получаем точку `t'`.
{% include image_svg.html src="/img/column-vector2d.svg" style="width: 246.793pt; height: 37.2836pt;"
alt="&x'=x_0+(x-x_0)cos\varphi-(y-y_0)sin\varphi,&\\&y'=y_0+(x-x_0)sin\varphi+(y-y_0)cos\varphi.&\\" %}
### Описание алгоритма {#algorithm-description}
Начало координат находится в верхнем левом углу, координатные оси направлены вправо и вниз. Центральная точка
для поворотов `t0` расположена в центре фигуры. Квадрат это массив из четырёх точек-вершин. Обходим массив
точек, поворачиваем каждую из них на угол, затем соединяем точки линиями и рисуем линии на холсте. Обновляем
картинку с частотой 20 кадров в секунду.
### Реализация {#implementation}
<div>
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
### HTML {#html1}
```html
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
```
### JavaScript {#javascript1}
```js
'use strict';
let canvas = document.getElementById('canvas');
// исходный массив точек-вершин квадрата
let square = [{x:50,y:50},{x:50,y:250},{x:250,y:250},{x:250,y:50}];
// центр фигуры, вокруг него будем выполнять поворот
let t0 = {x:150, y:150};
// угол поворота в градусах
let deg = 1;
```
```js
// поворот фигуры и обновление изображения
function repaint() {
// поворачиваем исходный массив точек на угол
for (let i = 0; i < square.length; i++)
square[i] = rotateOnDegree(t0, square[i], deg);
// рисуем текущий массив точек
drawFigure(canvas, square);
}
```
```js
// поворачиваем точку (t) на угол (deg) относительно точки (t0)
function rotateOnDegree(t0, t, deg) {
let t_new = {};
// переводим угол поворота из градусов в радианы
let rad = (Math.PI / 180) * deg;
// рассчитываем координаты новой точки по формуле
t_new.x = t0.x+(t.x-t0.x)*Math.cos(rad)-(t.y-t0.y)*Math.sin(rad);
t_new.y = t0.y+(t.x-t0.x)*Math.sin(rad)+(t.y-t0.y)*Math.cos(rad);
// возвращаем новую точку
return t_new;
}
```
```js
// рисуем фигуру по точкам из массива
function drawFigure(canvas, arr) {
let context = canvas.getContext('2d');
// очищаем весь холст целиком
context.clearRect(0, 0, canvas.width, canvas.height);
// обходим массив точек и соединяем их линиями
context.beginPath();
for (let i = 0; i < arr.length; i++)
if (i == 0)
context.moveTo(arr[i].x, arr[i].y);
else
context.lineTo(arr[i].x, arr[i].y);
context.closePath();
// рисуем линии на холсте
context.lineWidth = 2.2;
context.strokeStyle = '#222';
context.stroke();
}
```
```js
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
```
## Вращение в обратную сторону {#spinning-backwards}
Добавим ещё одну точку, которую будем вращать в обратную сторону. Точка удалена от центра фигуры на
четверть длины стороны квадрата. Сместим центр квадрата в эту точку сдвинем массив его вершин. Сам
квадрат будем вращать по часовой стрелке, а его центральную точку против часовой стрелки. Этот код
работает вместе с предыдущим.
<div>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
### HTML {#html2}
```html
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
```
### JavaScript {#javascript2}
```js
'use strict';
let canvas2 = document.getElementById('canvas2');
// текущий массив точек
let square2 = [];
// вращающаяся точка
let t2 = {x:100, y:100};
```
```js
// поворот фигуры и обновление изображения
function repaint2() {
// поворачиваем точку в обратную сторону
t2 = rotateOnDegree(t0, t2, -deg);
// обходим точки исходного массива и сдвигаем
for (let i = 0; i < square.length; i++) {
// текущая точка
square2[i] = {};
// сдвигаем точку исходного массива
square2[i].x = square[i].x - t0.x + t2.x;
square2[i].y = square[i].y - t0.y + t2.y;
}
// рисуем текущий массив точек
drawFigure(canvas2, square2);
}
```
```js
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint2,50));
```

View file

@ -0,0 +1,226 @@
---
title: Вращаем куб в пространстве
description: Рассматриваем разницу между параллельной и перспективной проекцией. Обе широко используются на практике для различных целей. В предыдущем примере мы вращали...
sections: [Линейная перспектива,Матрица поворота,Экспериментальная модель]
tags: [javascript,canvas,геометрия,графика,изображение,картинка,квадрат,куб]
scripts: [/js/classes-point-cube.js,/js/spinning-cube.js,/js/spinning-cube2.js]
styles: [/css/pomodoro1.css]
canonical_url: /ru/2023/01/10/spinning-cube-in-space.html
url_translated: /en/2023/01/11/spinning-cube-in-space.html
title_translated: Spinning cube in space
date: 2023.01.10
---
Рассматриваем разницу между параллельной и перспективной проекцией.
Обе широко используются на практике для различных целей. В предыдущем примере мы
[вращали квадрат на плоскости]({{ '/ru/2023/01/05/spinning-square-on-plane.html' | relative_url }})
переходим в трёхмерное пространство. Теперь, чтобы отобразить на плоскости экрана поворот трёхмерного
объекта, нужно сначала создать трёхмерный объект, повернуть его на угол, срисовать с него проекцию и
отобразить на экране уже проекцию.
Усложнённая модель, много кубиков: [Вращаем пространственный крест]({{ '/ru/2023/01/15/spinning-spatial-cross.html' | relative_url }}).
<div style="display: flex; flex-direction: row; flex-wrap: wrap;">
<div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Параллельная проекция</span>
<canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
<div style="display: flex; flex-direction: column;">
<span>Перспективная проекция</span>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
</div>
*Параллельная проекция* центр проекции бесконечно удалён от плоскости экрана наблюдателя,
размеры предметов выглядят одинаковыми.
*Перспективная проекция* параллельные линии сходятся в центре перспективы, предметы выглядят
уменьшающимися вдалеке.
## Экспериментальная модель {#experimental-model}
Размер куба 200, размер холста 300, начало координат находится в верхнем левом углу. Центр фигуры
в середине холста. Ось `X` направлена вправо, ось `Y` направлена вниз, ось `Z` направлена вдаль.
Выполняется поворот последовательно по всем трём осям: сначала по оси `X`, затем по оси `Y` и затем
по оси `Z`. Настройками модели можно управлять, например можно отключать лишнее вращение по осям и
изменять положение центра проекции на экране наблюдателя.
<div>
<canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
<form>
<div>
<span>Вращение по осям:</span>
<input type="checkbox" id="rotateX" name="rotateX" checked onchange="changeAxis('x',event)">
<label for="rotateX">X</label>
<input type="checkbox" id="rotateY" name="rotateY" checked onchange="changeAxis('y',event)">
<label for="rotateY">Y</label>
<input type="checkbox" id="rotateZ" name="rotateZ" checked onchange="changeAxis('z',event)">
<label for="rotateZ">Z</label>
</div>
<span>Центр на экране наблюдателя:</span>
<div>
<input type="range" id="rangeX" name="rangeX" min="0" max="300" value="150" step="1"
oninput="resultX.value = rangeX.valueAsNumber; changeTv('x',event)">
<label for="rangeX">X</label>
<output id="resultX" name="resultX">150</output>
</div>
<div>
<input type="range" id="rangeY" name="rangeY" min="0" max="300" value="150" step="1"
oninput="resultY.value = rangeY.valueAsNumber; changeTv('y',event)">
<label for="rangeY">Y</label>
<output id="resultY" name="resultY">150</output>
</div>
<div>
<input type="range" id="rangeZ" name="rangeZ" min="50" max="200" value="60" step="1"
oninput="resultZ.value = rangeZ.valueAsNumber; changeTv('z',event)">
<label for="rangeZ">Z</label>
<output name="resultZ">60</output>
</div>
<span>Удалённость центра проекции:</span>
<div>
<input type="range" id="distance" name="distance" min="220" max="800" value="300" step="10"
oninput="result.value = distance.valueAsNumber; changeDistance(event);">
<label for="distance">Z</label>
<output name="result">300</output>
</div>
<div>
<label for="center">Показать центральную точку:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div>
</form>
## Поворот точки в пространстве {#point-rotation-in-space}
Рассчитываем новые координаты точки по формулам матрицы поворота для трёхмерного пространства.
Поворачиваем точку `t` относительно точки `t0` получаем точку `t'`.
*Поворот по оси `X`.*
{% include image_svg.html src="/img/column-vector3dx.svg" style="width: 242.619pt; height: 59.0768pt;"
alt="&x'=x,&\\&y'=y_0+(y-y_0)cos\varphi-(z-z_0)sin\varphi,&\\&z'=z_0+(y-y_0)sin\varphi+(z-z_0)cos\varphi.&\\" %}
*Поворот по оси `Y`.*
{% include image_svg.html src="/img/column-vector3dy.svg" style="width: 246.251pt; height: 59.0768pt;"
alt="&x'=x_0+(x-x_0)cos\varphi-(z-z_0)sin\varphi,&\\&y'=y,&\\&z'=z_0+(x-x_0)sin\varphi+(z-z_0)cos\varphi.&\\" %}
*Поворот по оси `Z`.*
{% include image_svg.html src="/img/column-vector3dz.svg" style="width: 246.793pt; height: 55.4753pt;"
alt="&x'=x_0+(x-x_0)cos\varphi-(y-y_0)sin\varphi,&\\&y'=y_0+(x-x_0)sin\varphi+(y-y_0)cos\varphi,&\\&z'=z.&\\" %}
## Проекция точки {#point-projection}
Экспериментальные формулы с возможностью смещения центра проекции `d0` на экране наблюдателя `tv`.
Отображаем точку пространства `t` на плоскость экрана получаем точку `t'`.
*Параллельная проекция.*
{% include image_svg.html src="/img/oblique-projection.svg" style="width: 123.97pt; height: 37.2836pt;"
alt="&x'=x,&\\&y'=y+(y_v-z)/4.&\\" %}
*Перспективная проекция.*
{% include image_svg.html src="/img/central-projection.svg" style="width: 231.924pt; height: 37.2836pt;"
alt="&x'=x_v+d_0\cdot(x-x_v)/(z-z_v+d_0),&\\&y'=y_v+d_0\cdot(y-y_v)/(z-z_v+d_0).&\\" %}
*Расстояние от точки до центра проекции.*
{% include image_svg.html src="/img/euclidean-distance.svg" style="width: 319.911pt; height: 17.9328pt;"
alt="d(t,d_0)=\sqrt{(x-x_v)^2+(y-y_v)^2+(z-z_v+d_0)^2}." %}
## Сортировка граней {#face-sorting}
При создании кубика, вершины каждой грани задаём по часовой стрелке. При получении проекции, подставляем
в уравнение прямой три подряд идущие вершины, чтобы определить наклон грани и удалённость её от плоскости
проекции.
*Уравнение прямой, проходящей через две точки.*
{% include image_svg.html src="/img/linear-equation.svg" style="width: 137.171pt; height: 35.3194pt;"
alt="{(x-x_1)\over(y-y_1)}={(x_2-x_1)\over(y_2-y_1)}." %}
## Описание алгоритма {#algorithm-description}
Сначала обходим вершины куба и поворачиваем их на угол относительно центральной точки. Затем обходим грани
куба и получаем проекции входящих в них вершин. После этого сортируем проекции граней по удалённости. Затем
рисуем проекции на плоскости соединяем точки линиями. Рисуем полупрозрачным цветом сперва дальние грани и
поверх них ближние, чтобы сквозь ближние грани было видно дальние.
На каждом шаге отображения фигуры повторяем сортировку граней по удалённости, так как с изменением
угла поворота, координаты смещаются, и ближние грани становятся дальними.
## Реализация на JavaScript {#implementation-in-javascript}
{% include classes-point-cube-ru.md -%}
Создаём объект и рисуем две проекции на плоскости.
```js
'use strict';
// рисовать будем сразу две картинки,
// объект будет один, а проекций будет много
const canvas1 = document.getElementById('canvas1');
const canvas2 = document.getElementById('canvas2');
// создаём объект
const cube = new Cube(50,50,50,200);
// центр фигуры, вокруг него будем выполнять поворот
const t0 = new Point(150,150,150);
// удалённость центра проекции
const d = 300;
// положение экрана наблюдателя
const tv = new Point(150,150,80);
// угол поворота в градусах
const deg = {x:0,y:1,z:0};
```
```js
// поворот фигуры и обновление изображения
function repaint() {
cube.rotate(deg, t0);
// рисуем параллельную проекцию
drawFigure(canvas1, cube.projection('parallel', tv));
// рисуем перспективную проекцию
drawFigure(canvas2, cube.projection('perspective', tv, d));
}
```
```js
// рисуем фигуру по точкам из массива
function drawFigure(canvas, proj) {
let context = canvas.getContext('2d');
// сортируем грани по их наклону
proj.sort((a,b) => b.clock-a.clock);
// очищаем весь холст целиком
context.clearRect(0, 0, canvas.width, canvas.height);
// обходим массив граней куба
for (let i = 0; i < proj.length; i++) {
// обходим массив точек и соединяем их линиями
context.beginPath();
for (let j = 0; j < proj[i].length; j++) {
if (j == 0) {
context.moveTo(proj[i][j].x, proj[i][j].y);
} else {
context.lineTo(proj[i][j].x, proj[i][j].y);
}
}
context.closePath();
// рисуем грань куба вместе с рёбрами
context.lineWidth = 2.2;
context.lineJoin = 'round';
context.fillStyle = '#fff9';
context.strokeStyle = '#222';
context.fill();
context.stroke();
}
}
```
```js
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
```

View file

@ -0,0 +1,271 @@
---
title: Вращаем пространственный крест
description: Пишем алгоритм для поворота объёмной фигуры на угол вокруг своего центра по всем трём осям сразу. В предыдущем примере мы вращали куб в пространстве...
sections: [Объёмные фигуры,Матрица поворота,Экспериментальная модель]
tags: [javascript,canvas,геометрия,матрица,графика,изображение,картинка,квадрат,куб]
scripts: [/js/classes-point-cube.js,/js/spinning-spatial-cross.js,/js/spinning-spatial-cross2.js]
styles: [/css/pomodoro1.css]
canonical_url: /ru/2023/01/15/spinning-spatial-cross.html
url_translated: /en/2023/01/16/spinning-spatial-cross.html
title_translated: Spinning spatial cross
date: 2023.01.15
---
Пишем алгоритм для поворота объёмной фигуры на угол вокруг своего центра по всем трём осям сразу. В предыдущем
примере мы [вращали куб в пространстве]({{ '/ru/2023/01/10/spinning-cube-in-space.html' | relative_url }})
теперь кубиков будет много, алгоритм будет почти такой же и формулы будем использовать те же. Рисуем два
варианта фигуры: *пространственный крест* и *крест-куб* в двух типах проекций, рассматриваем разницу.
Тестирование экспериментального интерфейса: [Объёмный тетрис]({{ '/ru/2023/01/21/volumetric-tetris.html' | relative_url }}).
## Пространственный крест {#spatial-cross}
<div style="display: flex; flex-direction: row; flex-wrap: wrap;">
<div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Параллельная проекция</span>
<canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
<div style="display: flex; flex-direction: column;">
<span>Перспективная проекция</span>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
</div>
## Крест-куб {#cross-cube}
<div style="display: flex; flex-direction: row; flex-wrap: wrap;">
<div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Параллельная проекция</span>
<canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
<div style="display: flex; flex-direction: column;">
<span>Перспективная проекция</span>
<canvas id="canvas4" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
</div>
*Параллельная проекция* все кубики одинакового размера.
*Перспективная проекция* кубики выглядят уменьшающимися вдалеке.
## Экспериментальная модель {#experimental-model}
Слегка усложнённая версия из предыдущего примера теперь кубиков много. В дополнение к предыдущим настройкам
можно поменять: вариант фигуры *пространственный крест* или *крест-куб*, направление сортировки граней
*линейная перспектива* или *обратная перспектива* и прозрачность стенок кубиков.
<div>
<canvas id="canvas5" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p>
</canvas>
</div>
<div>
<form>
<div>
<span>Вращение по осям:</span>
<input type="checkbox" id="rotateX" name="rotateX" checked onchange="changeAxis('x',event)">
<label for="rotateX">X</label>
<input type="checkbox" id="rotateY" name="rotateY" checked onchange="changeAxis('y',event)">
<label for="rotateY">Y</label>
<input type="checkbox" id="rotateZ" name="rotateZ" checked onchange="changeAxis('z',event)">
<label for="rotateZ">Z</label>
</div>
<span>Центр на экране наблюдателя:</span>
<div>
<input type="range" id="rangeX" name="rangeX" min="0" max="300" value="150" step="1"
oninput="resultX.value = rangeX.valueAsNumber; changeTv('x',event)">
<label for="rangeX">X</label>
<output id="resultX" name="resultX">150</output>
</div>
<div>
<input type="range" id="rangeY" name="rangeY" min="0" max="300" value="150" step="1"
oninput="resultY.value = rangeY.valueAsNumber; changeTv('y',event)">
<label for="rangeY">Y</label>
<output id="resultY" name="resultY">150</output>
</div>
<div>
<input type="range" id="rangeZ" name="rangeZ" min="50" max="220" value="125" step="1"
oninput="resultZ.value = rangeZ.valueAsNumber; changeTv('z',event)">
<label for="rangeZ">Z</label>
<output name="resultZ">125</output>
</div>
<span>Удалённость центра проекции:</span>
<div>
<input type="range" id="distance" name="distance" min="220" max="800" value="300" step="10"
oninput="result.value = distance.valueAsNumber; changeDistance(event);">
<label for="distance">Z</label>
<output name="result">300</output>
</div>
<div>
<label for="center">Показать центральную точку:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div>
<span>Прозрачность кубиков:</span>
<div>
<input type="range" id="alpha" name="alpha" min="0" max="100" step="1" value="20"
oninput="oAlpha.value = alpha.valueAsNumber + '%'; changeAlpha(event)">
<label for="alpha">A</label>
<output name="oAlpha">20%</output>
</div>
</form>
<span>Вариант фигуры:</span>
<form oninput="changeFigure(event)">
<input type="radio" id="first" name="figure" value="first">
<label for="first">Крест</label>
<input type="radio" id="second" name="figure" value="second" checked>
<label for="second">Куб</label>
</form>
<span>Перспективная проекция:</span>
<form oninput="changeOrder(event)">
<input type="radio" id="linear" name="order" value="linear" checked>
<label for="linear">Линейная</label>
<input type="radio" id="reverse" name="order" value="reverse">
<label for="reverse">Обратная</label>
</form>
</div>
## Описание алгоритма {#algorithm-description}
Подготавливаем матрицу из нулей и единиц, где единица означает кубик в определенном месте фигуры. Затем
обходим эту матрицу и заполняем массив кубиков с соответствующими координатами вершин. После этого запускаем
вращение по всем трём осям сразу. На каждом шаге обходим массив кубиков и получаем проекции их граней. Затем
сортируем массив граней по удалённости от центра проекции, обходим этот массив и выкидываем из него одинаковые
пары это есть смежные стенки между соседними кубиками внутри фигуры. После этого полупрозрачным цветом рисуем
грани кубиков сначала дальние и затем ближние, чтобы через ближние грани было видно дальние.
## Реализация на JavaScript {#implementation-in-javascript}
{% include classes-point-cube-ru.md -%}
Создаём объекты по шаблонам и рисуем их проекции на плоскости.
```js
'use strict';
// матрицы-шаблоны для кубиков
const shape1 = [ // пространственный крест
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]],
[[0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]];
const shape2 = [ // крест-куб
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]],
[[0,0,1,0,0], [0,0,0,0,0], [1,0,0,0,1], [0,0,0,0,0], [0,0,1,0,0]],
[[1,1,1,1,1], [1,0,0,0,1], [1,0,0,0,1], [1,0,0,0,1], [1,1,1,1,1]],
[[0,0,1,0,0], [0,0,0,0,0], [1,0,0,0,1], [0,0,0,0,0], [0,0,1,0,0]],
[[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]]];
// размер кубика, количество кубиков в ряду, отступ
const size = 40, row = 5, gap = 50;
// массивы для кубиков
const cubes1 = [], cubes2 = [];
// обходим матрицы, заполняем массивы кубиками
for (let x=0; x<row; x++)
for (let y=0; y<row; y++)
for (let z=0; z<row; z++) {
if (shape1[x][y][z]==1)
cubes1.push(new Cube(x*size+gap,y*size+gap,z*size+gap,size));
if (shape2[x][y][z]==1)
cubes2.push(new Cube(x*size+gap,y*size+gap,z*size+gap,size));
}
// центр фигуры, вокруг него будем выполнять поворот
const t0 = new Point(150,150,150);
// удалённость центра проекции
const d = 300;
// положение экрана наблюдателя
const tv = new Point(150,150,125);
// угол поворота в градусах
const deg = {x:1,y:1,z:1};
```
```js
// рисовать будем по две картинки для каждой фигуры
const canvas1 = document.getElementById('canvas1');
const canvas2 = document.getElementById('canvas2');
const canvas3 = document.getElementById('canvas3');
const canvas4 = document.getElementById('canvas4');
// обновление изображения
function repaint() {
// пространственный крест
processFigure(cubes1,canvas1,canvas2);
// крест-куб
processFigure(cubes2,canvas3,canvas4);
}
```
```js
// поворачиваем фигуру и получаем проекции
function processFigure(cubes,cnv1,cnv2) {
// массивы проекций граней кубиков
let parallel = [], perspective = [];
// поворачиваем кубики и получаем проекции
for (let cube of cubes) {
cube.rotate(deg, t0);
parallel = parallel.concat(cube.projection('parallel',tv,d));
perspective = perspective.concat(cube.projection('perspective',tv,d));
}
// смежные стенки между соседними кубиками не рисуем
noAdjacent(parallel);
noAdjacent(perspective);
// сортируем грани разных кубиков по удалённости и внутри одного кубика по наклону
parallel.sort((a,b)=>Math.abs(b.dist-a.dist)>size ? b.dist-a.dist : b.clock-a.clock);
// сортируем грани по удалённости от центра проекции
perspective.sort((a,b)=>b.dist-a.dist);
// рисуем параллельную проекцию
drawFigure(cnv1, parallel);
// рисуем перспективную проекцию
drawFigure(cnv2, perspective);
}
```
```js
// смежные стенки между соседними кубиками не рисуем
function noAdjacent(array) {
// сортируем грани по удалённости
array.sort((a,b) => b.dist-a.dist);
// удаляем смежные стенки между кубиками
for (let i=0, j=1; i<array.length-1; j=++i+1)
while (j<array.length && Cube.pEquidistant(array[i],array[j]))
if (Cube.pAdjacent(array[i],array[j])) {
array.splice(j,1);
array.splice(i,1);
i--; j=array.length;
} else j++;
}
```
```js
// рисуем фигуру по точкам из массива
function drawFigure(canvas, proj, alpha=0.8) {
const context = canvas.getContext('2d');
// очищаем весь холст целиком
context.clearRect(0, 0, canvas.width, canvas.height);
// обходим массив граней куба
for (let i = 0; i < proj.length; i++) {
// обходим массив точек и соединяем их линиями
context.beginPath();
for (let j = 0; j < proj[i].length; j++) {
if (j == 0) {
context.moveTo(proj[i][j].x, proj[i][j].y);
} else {
context.lineTo(proj[i][j].x, proj[i][j].y);
}
}
context.closePath();
// рисуем грань куба вместе с рёбрами
context.lineWidth = 1.9;
context.lineJoin = 'round';
context.fillStyle = 'rgba(200,230,201,'+alpha+')';
context.strokeStyle = 'rgba(102,187,106,'+(0.2+alpha)+')';
context.fill();
context.stroke();
}
}
```
```js
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
```

View file

@ -0,0 +1,50 @@
---
title: Объёмный тетрис
description: Общеобразовательная игра в широком смысле этого слова. При изучении языков программирования рекомендуется сначала написать свою версию и потом использовать...
sections: [Логическая игра,Экспериментальный интерфейс]
tags: [javascript,canvas,игра,головоломка,геометрия,матрица,графика,квадрат,куб,3d,трёхмерный]
scripts: [/js/classes-point-cube.js,/js/tetris-figures.js,/js/tetris-model.js,/js/tetris-controller.js,/js/tetris-view.js]
styles: [/css/pomodoro1.css]
canonical_url: /ru/2023/01/21/volumetric-tetris.html
url_translated: /en/2023/01/22/volumetric-tetris.html
title_translated: Volumetric tetris
date: 2023.01.21
---
Общеобразовательная игра в широком смысле этого слова. При изучении языков программирования рекомендуется
сначала написать свою версию и потом использовать её для демонстрации и тестирования другого программного
обеспечения или оборудования. Трёхмерный интерфейс написан на JavaScript Canvas логика самой игры двухмерная.
Описание алгоритма графики: [Вращаем куб в пространстве]({{ '/ru/2023/01/10/spinning-cube-in-space.html' | relative_url }}).
## Экспериментальный интерфейс {#experimental-interface}
По умолчанию выключен можно просто играть в тетрис. В дополнение к плоской версии добавлены два объёмных
варианта: *параллельная проекция* и *перспективная проекция* параметры для каждого из них можно изменять.
Для перспективной проекции: можно изменять положение экрана наблюдателя и удалённость источника проекции.
Наблюдатель смотрит в центр изображения, а центр проекции удалён на расстояние, сопоставимое с размерами
игрового поля. Для параллельной проекции: можно изменять вертикальное положение. Для обеих проекций: можно
поворачивать игровое поле по всем трём осям. Центральная точка для поворотов это центральная нижняя дальняя
точка поля. Для всех вариантов изображения: размер кубика 32, размер квадратика 30 и отступ 2.
Начало координат расположено в верхней левой точке, оси направлены: `X` вправо, `Y` вниз и `Z` вдаль.
*Пример использования:* начинаем игру, набираем какое-то количество фигур на поле, затем ставим игру на паузу,
и переключаемся между вариантами объёмного изображения, поворачиваем поле с фигурами, изменяем настройки.
{% include volumetric-tetris-ru.html -%}
## Игровой процесс {#gaming-process}
Управление: кнопки на клавиатуре со стрелками вправо, влево, вверх, вниз и кнопка пауза `pause`.
Игровые очки начисляются за полностью собранные строки из элементов фигур. Количество набранных очков зависит
от количества собранных строк, по 10 очков за каждую строку, если в строке 10 кубиков, и кратно увеличивается,
если одновременно собрано: 2 строки в 3 раза, 3 строки в 5 раз, 4 строки в 10 раз.
Особенность игры: собранные строки сначала моргают и после этого исчезают, при этом игровой процесс на это
время не приостанавливается текущая фигура продолжает падать.
Уровень увеличивается при сборе 10 заполненных строк, то есть 100 очков, если в строке 10 кубиков. На каждом
новом уровне, скорость фигур повышается и на 21 уровне достигает максимума. В режиме улитки скорость повышается
в 5 раз медленнее и достигает максимума на 104 уровне. Текущая скорость отображается над игровым полем в виде
индикатора `meter`.

46
jekyll_site/ru/index.md Normal file
View file

@ -0,0 +1,46 @@
---
title: Код с комментариями
description: Заметки на тему программирования с примерами кода и комментариями. Решения задач и описания решений.
sections: [Решения задач и описания решений]
tags: [javascript,canvas,геометрия,матрица,алгоритмы,реализация,графика,изображения,картинки,квадрат,куб]
canonical_url: /
url_translated: /en/
title_translated: Code with comments
---
{%- assign articles = "" | split: "" %}
{%- assign articles = articles | push: "Объёмный тетрис" %}
{%- capture article_brief %}
Общеобразовательная игра в широком смысле этого слова. При изучении языков программирования рекомендуется
сначала написать свою версию и потом использовать её для демонстрации и тестирования другого программного
обеспечения или оборудования. Трёхмерный интерфейс написан на JavaScript Canvas логика самой игры двухмерная.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Вращаем пространственный крест" %}
{%- capture article_brief %}
Пишем алгоритм для поворота объёмной фигуры на угол вокруг своего центра по всем трём осям сразу. В предыдущем
примере мы вращали куб в пространстве теперь кубиков будет много, алгоритм будет почти такой же и формулы
будем использовать те же. Рисуем два варианта фигуры: *пространственный крест* и *крест-куб* в двух типах проекций,
рассматриваем разницу.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Вращаем куб в пространстве" %}
{%- capture article_brief %}
Рассматриваем разницу между параллельной и перспективной проекцией. Обе широко используются на практике для
различных целей. В предыдущем примере мы вращали квадрат на плоскости переходим в трёхмерное пространство.
Теперь, чтобы отобразить на плоскости экрана поворот трёхмерного объекта, нужно сначала создать трёхмерный
объект, повернуть его на угол, срисовать с него проекцию и отобразить на экране уже проекцию.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Вращаем квадрат на плоскости" %}
{%- capture article_brief %}
Напишем алгоритм на JavaScript для поворота квадрата на угол вокруг своего центра, повторим программу
средней школы. Для расчётов будем использовать класс `Math`, а для отображения результатов Canvas.
Начало координат находится в верхнем левом углу, координатные оси направлены вправо и вниз. Центральная точка
для поворотов `t0` расположена в центре фигуры. Квадрат это массив из четырёх точек-вершин. Обходим массив
точек, поворачиваем каждую из них на угол, затем соединяем точки линиями и рисуем линии на холсте. Обновляем
картинку с частотой 20 кадров в секунду.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- include main_page.html articles = articles -%}

5
package.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash
echo "Подготовка архива для последующего развёртывания."
cd _site || exit
rm -rf ../pomodoro1.zip
7z a ../pomodoro1.zip ./*

4
serve.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
echo "Локальное развёртывание для проверки корректности сборки."
jekyll serve --skip-initial-build --disable-disk-cache --host localhost
echo "Адрес сервера: http://localhost:4000"