Compare commits

...

10 commits

Author SHA1 Message Date
2adcb73c8b 2024-12-29 2024-12-29 10:39:46 +03:00
b711b965a3 2024-09-30 2024-10-01 18:02:30 +03:00
ccc67783d0 2024-08-31 2024-09-01 08:46:26 +03:00
1e2821bd04 2024-07-31 2024-07-31 21:12:26 +03:00
d5b064adcc 2024-04-30 2024-05-02 20:38:40 +03:00
e3c61f7d78 2024-03-31 2024-03-31 02:16:56 +03:00
6c235d1b4c 2024-02-29 2024-02-29 22:57:44 +03:00
e7072bf822 2023-12-30 2023-12-31 00:01:26 +03:00
80533ed026 2023-11-30 2023-12-17 09:49:38 +03:00
f2e0e0f461 2023-10-31 2023-12-17 09:39:19 +03:00
23 changed files with 209 additions and 213 deletions

View file

@ -6,8 +6,6 @@
│ ├─ <a href='jekyll_site/_includes'>_includes</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-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/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-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/_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/css'>css</a>/<a href='jekyll_site/css/pomodoro1.css'>pomodoro1.css</a>

View file

@ -1,4 +1,4 @@
© Головин Г.Г., 2021-2023 © Головин Г.Г., 2021-2024
Опубликовано под [Открытой лицензией 1.1](OPEN_LICENSE.txt) Опубликовано под [Открытой лицензией 1.1](OPEN_LICENSE.txt)
@ -8,7 +8,7 @@
--- ---
© Golovin G.G., translation from Russian, 2021-2023 © Golovin G.G., translation from Russian, 2021-2024
Published under the [Open License 1.1](OPEN_LICENSE.txt) Published under the [Open License 1.1](OPEN_LICENSE.txt)

View file

@ -1,39 +1,37 @@
#!/bin/bash #!/bin/bash
echo "Сборка сайта в двух помидорных темах и оптимизация результатов." echo "Сборка сайта в двух помидорных темах и оптимизация результатов."
currentTimeMillis=$(date '+%s%3N') time_ms="$(date '+%s%3N')"
rm -rf _site # удаление каталогов предыдущей сборки, если таковые имеются
rm -rf _site_older find . -maxdepth 1 -type d -name "_site*" -exec rm -rf {} \;
rm -rf _site_color # сборка сайта в двух помидорных темах
echo "Сборка старого помидора." function jekyll_build {
mkdir -p _site_older case "$1" in
cp -r jekyll_site/_includes _site_older "older") echo "Сборка старого помидора." ;;
cp -r jekyll_site/ru _site_older "color") echo "Сборка цветного помидора." ;;
cp -r jekyll_site/en _site_older *) return ;; # две помидорные темы оформления
cp -r jekyll_site/ru/index.md _site_older esac
cp -r jekyll_site/_config_older.yml _site_older/_config.yml mkdir -p "_site_$1"
cp -r jekyll_site/Gemfile_older _site_older/Gemfile cp -r "jekyll_site/_includes" "_site_$1"
cd _site_older || exit cp -r "jekyll_site/ru" "_site_$1"
jekyll build --disable-disk-cache cp -r "jekyll_site/en" "_site_$1"
cp -r _site .. cp -r "jekyll_site/ru/index.md" "_site_$1"
cd .. cp -r "jekyll_site/_config_$1.yml" "_site_$1/_config.yml"
echo "Сборка цветного помидора." cp -r "jekyll_site/Gemfile_$1" "_site_$1/Gemfile"
mkdir -p _site_color cd "_site_$1" || return
cp -r jekyll_site/_includes _site_color jekyll build --disable-disk-cache --quiet
cp -r jekyll_site/ru _site_color }
cp -r jekyll_site/en _site_color export -f jekyll_build
cp -r jekyll_site/ru/index.md _site_color # запуск параллельной сборки сайта в двух помидорных темах оформления
cp -r jekyll_site/_config_color.yml _site_color/_config.yml printf 'jekyll_build "%s"\0' {older,color} | xargs -n1 -0 -P0 bash -c
cp -r jekyll_site/Gemfile_color _site_color/Gemfile # объединение двух сборок
cd _site_color || exit cp -r _site_older/_site .
jekyll build --disable-disk-cache cp -r _site_color/_site ./_site/color
cp -r _site ../_site/color # копирование без сборки
cd ..
echo "Копирование без сборки."
cp -r jekyll_site/css _site cp -r jekyll_site/css _site
cp -r jekyll_site/img _site cp -r jekyll_site/img _site
cp -r jekyll_site/js _site cp -r jekyll_site/js _site
cp -r jekyll_site/robots.txt _site cp -r jekyll_site/robots.txt _site
echo "Оптимизация собранного контента." # оптимизация собранного контента
cd _site || exit cd _site || exit
cp -r assets/* . cp -r assets/* .
rm -r assets rm -r assets
@ -41,16 +39,22 @@ rm -r color/assets/favicon.ico
cp -r color/assets/* . cp -r color/assets/* .
rm -r color/assets rm -r color/assets
rm -r color/404.html rm -r color/404.html
find . -type f -name '*.html' | sort -r | while read -r file; do rm -r color/return.html
sed -i 's/layout-padding=""/layout-padding/g' "$file" # шаблоны для оптимизации ряда тегов
sed -i 's/ class="language-plaintext highlighter-rouge"//g' "$file" expr+=('s|layout-padding=""|layout-padding|g')
sed -i 's/ class="language-java highlighter-rouge"//g' "$file" expr+=('s| class="language-plaintext highlighter-rouge"||g')
sed -i 's/ class="language-html highlighter-rouge"//g' "$file" expr+=('s| class="language-java highlighter-rouge"||g')
sed -i 's/ class="language-js highlighter-rouge"//g' "$file" expr+=('s| class="language-html highlighter-rouge"||g')
sed -i 's/<div><div class="highlight"><pre class="highlight">/<div class="highlight"><pre class="highlight">/g' "$file" expr+=('s| class="language-js highlighter-rouge"||g')
sed -i 's/<\/code><\/pre><\/div><\/div>/<\/code><\/pre><\/div>/g' "$file" expr+=('s|<div><div class="highlight">|<div class="highlight">|g')
sed -i 's/<hr \/>/<hr>/g' "$file" expr+=('s|</pre></div></div>|</pre></div>|g')
sed -i -r 's/<input(.+) \/>/<input\1>/g' "$file" expr+=('s|<hr />|<hr>|g')
sed -i -r 's/<img(.+) \/>/<img\1>/g' "$file" expr+=('s|<input(.+) />|<input\1>|g')
done expr+=('s|<img(.+) />|<img\1>|g')
echo "Время выполнения сборки: $(("$(date '+%s%3N')" - "$currentTimeMillis")) мс." # запуск параллельной обработки собранных страниц и оптимизация ряда тегов
find . -type f -name "*.html" -printf '%p\0' | xargs -I{} -n1 -0 -P0 bash -c \
"echo 'Оптимизация: {}' && sed -i -E $(printf " -e '%s'" "${expr[@]}") '{}'"
# переход в корень сайта для каталогов без заглавной страницы
find . -type d -exec cp -n return.html {}/index.html \;
rm -r return.html
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."

View file

@ -4,12 +4,12 @@ name: "Код с комментариями"
name_translated: "Code with comments" name_translated: "Code with comments"
# URL адрес сайта, включая протокол # URL адрес сайта, включая протокол
url: "https://pomodoro1.mircloud.ru" url: "https://pomodoro1.mircloud.ru"
# подпапка этой сборки для относительных URLs # подпапка этой сборки для относительных URL-ов
baseurl: "/color" baseurl: "/color"
# ссылка в верхнем левом углу заглавных страниц # ссылка в верхнем левом углу заглавных страниц
homepage_url: "https://git.org.ru/pomodoro/1" homepage_url: "https://gitea.com/pomodoro/1"
# представление ссылки # представление ссылки
homepage_name: "GIT.ORG.RU" homepage_name: "GITEA"
# подпапка альтернативной сборки # подпапка альтернативной сборки
older_tomato_baseurl: "" older_tomato_baseurl: ""
# часовой пояс для формата даты ISO-8601 # часовой пояс для формата даты ISO-8601
@ -20,6 +20,9 @@ author: "Головин Г.Г."
author_translated: "Golovin G.G." author_translated: "Golovin G.G."
# дополнение к подписи в футере для переведённых страниц # дополнение к подписи в футере для переведённых страниц
translation_caption: "translation from Russian" translation_caption: "translation from Russian"
# номера счётчиков для страниц
live_internet: "pomodoro"
yandex_metrika: "95699479"
# тема оформления для сборки # тема оформления для сборки
theme: color-tomato-theme theme: color-tomato-theme
# макет для сборки # макет для сборки

View file

@ -4,12 +4,12 @@ name: "Код с комментариями"
name_translated: "Code with comments" name_translated: "Code with comments"
# URL адрес сайта, включая протокол # URL адрес сайта, включая протокол
url: "https://pomodoro1.mircloud.ru" url: "https://pomodoro1.mircloud.ru"
# подпапка этой сборки для относительных URLs # подпапка этой сборки для относительных URL-ов
baseurl: "" baseurl: ""
# ссылка в верхнем левом углу заглавных страниц # ссылка в верхнем левом углу заглавных страниц
homepage_url: "https://git.org.ru/pomodoro/1" homepage_url: "https://gitea.com/pomodoro/1"
# представление ссылки # представление ссылки
homepage_name: "GIT.ORG.RU" homepage_name: "GITEA"
# подпапка альтернативной сборки # подпапка альтернативной сборки
color_tomato_baseurl: "/color" color_tomato_baseurl: "/color"
# часовой пояс для формата даты ISO-8601 # часовой пояс для формата даты ISO-8601
@ -20,6 +20,9 @@ author: "Головин Г.Г."
author_translated: "Golovin G.G." author_translated: "Golovin G.G."
# дополнение к подписи в футере для переведённых страниц # дополнение к подписи в футере для переведённых страниц
translation_caption: "translation from Russian" translation_caption: "translation from Russian"
# номера счётчиков для страниц
live_internet: "pomodoro"
yandex_metrika: "95699479"
# тема оформления для сборки # тема оформления для сборки
theme: older-tomato-theme theme: older-tomato-theme
# макет для сборки # макет для сборки

View file

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

View file

@ -1,16 +0,0 @@
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-1L7J3YNRZ7"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-1L7J3YNRZ7');
</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

@ -17,12 +17,12 @@
<div style="display: flex; flex-direction: row; align-items: start; flex-wrap: wrap;"> <div style="display: flex; flex-direction: row; align-items: start; flex-wrap: wrap;">
<div style="padding: 0 8px 8px 0;"> <div style="padding: 0 8px 8px 0;">
<canvas id="container"> <canvas id="container">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
<div style="padding: 0 8px 8px 0;"> <div style="padding: 0 8px 8px 0;">
<canvas id="next"> <canvas id="next">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
<div style="display: flex; flex-direction: column; align-items: start;"> <div style="display: flex; flex-direction: column; align-items: start;">
@ -102,7 +102,7 @@
<label for="dist">Z</label> <label for="dist">Z</label>
<output id="oDist" name="oDist">640</output> <output id="oDist" name="oDist">640</output>
</div> </div>
<label for="center">Show the central point:</label> <label for="center">Move the central point:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)"> <input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div> </div>
</div> </div>

View file

@ -17,12 +17,12 @@
<div style="display: flex; flex-direction: row; align-items: start; flex-wrap: wrap;"> <div style="display: flex; flex-direction: row; align-items: start; flex-wrap: wrap;">
<div style="padding: 0 8px 8px 0;"> <div style="padding: 0 8px 8px 0;">
<canvas id="container"> <canvas id="container">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
<div style="padding: 0 8px 8px 0;"> <div style="padding: 0 8px 8px 0;">
<canvas id="next"> <canvas id="next">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
<div style="display: flex; flex-direction: column; align-items: start;"> <div style="display: flex; flex-direction: column; align-items: start;">
@ -102,7 +102,7 @@
<label for="dist">Z</label> <label for="dist">Z</label>
<output id="oDist" name="oDist">640</output> <output id="oDist" name="oDist">640</output>
</div> </div>
<label for="center">Показать центральную точку:</label> <label for="center">Двигать центральную точку:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)"> <input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div> </div>
</div> </div>

View file

@ -35,7 +35,7 @@ with lines and draw lines on the canvas. We renew the image at a frequency of 20
<div> <div>
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
@ -43,7 +43,7 @@ with lines and draw lines on the canvas. We renew the image at a frequency of 20
```html ```html
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
``` ```
@ -116,7 +116,7 @@ central point — counterclockwise. This code works in conjunction with the prev
<div> <div>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
@ -124,7 +124,7 @@ central point — counterclockwise. This code works in conjunction with the prev
```html ```html
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
``` ```

View file

@ -2,7 +2,7 @@
title: Spinning cube in space 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... 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] sections: [Linear perspective,Rotation matrix,Experimental model]
tags: [javascript,online,canvas,geometry,graphics,image,picture,square,cube] tags: [javascript,online,canvas,geometry,graphics,image,picture,square,cube,3d,three-dimensional]
scripts: [/js/classes-point-cube.js,/js/spinning-cube.js,/js/spinning-cube2.js] scripts: [/js/classes-point-cube.js,/js/spinning-cube.js,/js/spinning-cube2.js]
styles: [/css/pomodoro1.css] styles: [/css/pomodoro1.css]
canonical_url: /en/2023/01/11/spinning-cube-in-space.html canonical_url: /en/2023/01/11/spinning-cube-in-space.html
@ -18,6 +18,7 @@ are widely used in practice for various purposes. In the previous example, we
we pass into three-dimensional space. Now, to display the rotation of a three-dimensional object 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 *mathematical model* of a three-dimensional object, on the screen plane, we first need to create a *mathematical model* of a three-dimensional object,
rotate it by an angle, draw a projection from it and display already the projection on the screen. rotate it by an angle, draw a projection from it and display already the projection on the screen.
For clarity, we will use the cartesian coordinate system.
Complicated model, many cubes: [Spinning spatial cross]({{ '/en/2023/01/16/spinning-spatial-cross.html' | relative_url }}). Complicated model, many cubes: [Spinning spatial cross]({{ '/en/2023/01/16/spinning-spatial-cross.html' | relative_url }}).
@ -25,13 +26,13 @@ Complicated model, many cubes: [Spinning spatial cross]({{ '/en/2023/01/16/spinn
<div style="display: flex; flex-direction: column; padding-right: 8px;"> <div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Parallel projection</span> <span>Parallel projection</span>
<canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
<div style="display: flex; flex-direction: column;"> <div style="display: flex; flex-direction: column;">
<span>Perspective projection</span> <span>Perspective projection</span>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
</div> </div>
@ -48,12 +49,12 @@ Cube size 200, canvas size 300, origin of coordinates is in the upper left corne
is in the middle of the canvas. The `X` axis is directed to the right, the `Y` axis is directed downwards, 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 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, 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 for example, you can switch off redundant rotation around the axes and move the central point of the projection
center onto the observer screen. onto the observer screen.
<div> <div>
<canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
<form> <form>
@ -93,7 +94,7 @@ center onto the observer screen.
<output name="result">300</output> <output name="result">300</output>
</div> </div>
<div> <div>
<label for="center">Show the central point:</label> <label for="center">Move the central point:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)"> <input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div> </div>
</form> </form>
@ -154,8 +155,8 @@ alt="{(x-x_1)\over(y-y_1)}={(x_2-x_1)\over(y_2-y_1)}." %}
First, we bypass the vertices of the cube and rotate them by an angle relative to the center point. Then 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 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 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 with lines. We draw with an almost transparent color first the far faces and atop them the near ones,
the far faces can be seen through 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 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. with a change in the angle of rotation, the coordinates shift, and the near faces become far.

View file

@ -1,8 +1,8 @@
--- ---
title: Spinning spatial cross 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... description: We are writing an algorithm for rotating a three-dimensional figure around its center along all three axes at once. In the previous example, we rotated cube...
sections: [Volumetric figures,Rotation matrix,Experimental model] sections: [Volumetric figures,Rotation matrix,Experimental model]
tags: [javascript,online,canvas,geometry,matrix,graphics,image,picture,square,cube] tags: [javascript,online,canvas,geometry,matrix,graphics,image,picture,square,cube,3d,three-dimensional]
scripts: [/js/classes-point-cube.js,/js/spinning-spatial-cross.js,/js/spinning-spatial-cross2.js] scripts: [/js/classes-point-cube.js,/js/spinning-spatial-cross.js,/js/spinning-spatial-cross2.js]
styles: [/css/pomodoro1.css] styles: [/css/pomodoro1.css]
canonical_url: /en/2023/01/16/spinning-spatial-cross.html canonical_url: /en/2023/01/16/spinning-spatial-cross.html
@ -12,12 +12,12 @@ date: 2023.01.16
lang: en lang: en
--- ---
We are writing an algorithm for rotating a three-dimensional figure by an angle We are writing an algorithm for rotating a three-dimensional figure around
around its center along all three axes at once. In the previous example, we 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 }}) [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. in this example, there are a lot of cubes, the algorithm will be almost the same, and we will use
We draw two variants of the figure: *spatial cross* and *cross-cube* in two types of projections, the same formulas. For clarity, let's take two variants of a symmetrical volumetric figure in two
consider the difference. types of projections *spatial cross* and *cross-cube* we consider the difference between them.
Testing the experimental interface: [Volumetric tetris]({{ '/en/2023/01/22/volumetric-tetris.html' | relative_url }}). Testing the experimental interface: [Volumetric tetris]({{ '/en/2023/01/22/volumetric-tetris.html' | relative_url }}).
@ -27,13 +27,13 @@ Testing the experimental interface: [Volumetric tetris]({{ '/en/2023/01/22/volum
<div style="display: flex; flex-direction: column; padding-right: 8px;"> <div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Parallel projection</span> <span>Parallel projection</span>
<canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
<div style="display: flex; flex-direction: column;"> <div style="display: flex; flex-direction: column;">
<span>Perspective projection</span> <span>Perspective projection</span>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
</div> </div>
@ -44,13 +44,13 @@ Testing the experimental interface: [Volumetric tetris]({{ '/en/2023/01/22/volum
<div style="display: flex; flex-direction: column; padding-right: 8px;"> <div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Parallel projection</span> <span>Parallel projection</span>
<canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
<div style="display: flex; flex-direction: column;"> <div style="display: flex; flex-direction: column;">
<span>Perspective projection</span> <span>Perspective projection</span>
<canvas id="canvas4" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas4" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
</div> </div>
@ -62,12 +62,12 @@ Testing the experimental interface: [Volumetric tetris]({{ '/en/2023/01/22/volum
{% include heading.html text="Experimental model" hash="experimental-model" %} {% include heading.html text="Experimental model" hash="experimental-model" %}
Slightly complicated version from the previous example now there are a lot of cubes. In addition to the 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 previous settings there can be changed: variant of the figure *spatial cross* or *cross-cube*, face sorting
direction *linear perspective* or *reverse perspective* and transparency of the cube walls. direction *straight perspective* or *reverse perspective* and transparency of the cube walls.
<div> <div>
<canvas id="canvas5" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas5" width="300" height="300" style="border: 1px solid gray;">
<p>Your browser does not support Canvas</p> <p>Canvas for displaying computations results</p>
</canvas> </canvas>
</div> </div>
<div> <div>
@ -108,7 +108,7 @@ direction — *linear perspective* or *reverse perspective* and transparency of
<output name="result">300</output> <output name="result">300</output>
</div> </div>
<div> <div>
<label for="center">Show the central point:</label> <label for="center">Move the central point:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)"> <input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div> </div>
<span>Transparency of cubes:</span> <span>Transparency of cubes:</span>
@ -126,10 +126,10 @@ direction — *linear perspective* or *reverse perspective* and transparency of
<input type="radio" id="second" name="figure" value="second" checked> <input type="radio" id="second" name="figure" value="second" checked>
<label for="second">Cube</label> <label for="second">Cube</label>
</form> </form>
<span>Perspective projection:</span> <span>Linear perspective:</span>
<form oninput="changeOrder(event)"> <form oninput="changeOrder(event)">
<input type="radio" id="linear" name="order" value="linear" checked> <input type="radio" id="linear" name="order" value="linear" checked>
<label for="linear">Linear</label> <label for="linear">Straight</label>
<input type="radio" id="reverse" name="order" value="reverse"> <input type="radio" id="reverse" name="order" value="reverse">
<label for="reverse">Reverse</label> <label for="reverse">Reverse</label>
</form> </form>
@ -137,13 +137,13 @@ direction — *linear perspective* or *reverse perspective* and transparency of
{% include heading.html text="Algorithm description" hash="algorithm-description" %} {% include heading.html text="Algorithm description" hash="algorithm-description" %}
We prepare a matrix of zeros and ones, where one means a cube in a certain place of the figure. Then we We prepare a three-dimensional matrix of zeros and ones, where one means a cube in a certain place of the figure.
bypass this matrix and fill in the array of cubes with the corresponding coordinates of the vertices. After Then we bypass this matrix and fill in the array of cubes with the corresponding coordinates of the vertices.
that, we start the rotation along all three axes at once. At each step, we bypass the array of cubes and get After that, we start the rotation along all three axes at once. At each step, we bypass the array of cubes and
projections of their faces. Then we sort the array of faces by remoteness from the projection center, bypass 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 this array and throw away the same pairs from it these are the adjacent walls between neighboring cubes inside
inside the figure. After that we draw cube faces with a translucent color first the distant and then the the figure. After that we draw with a translucent color the cube faces first the distant, and then the near ones,
near ones, so that the distant faces can be seen through the near ones. so that the distant faces can be seen through the near ones.
{% include heading.html text="Implementation in JavaScript" hash="implementation-in-javascript" %} {% include heading.html text="Implementation in JavaScript" hash="implementation-in-javascript" %}

View file

@ -1,8 +1,8 @@
--- ---
title: Volumetric tetris 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... description: General educational game in the broad meaning of this word. In the process of learning programming languages, it is recommended to write your own version...
sections: [Logical game,Experimental interface] sections: [Logical game,Experimental interface]
tags: [javascript,online,canvas,game,puzzle,geometry,matrix,graphics,square,cube,3d,three-dimensional] tags: [javascript,online,canvas,game,classic,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] 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] styles: [/css/pomodoro1.css]
canonical_url: /en/2023/01/22/volumetric-tetris.html canonical_url: /en/2023/01/22/volumetric-tetris.html
@ -12,17 +12,17 @@ date: 2023.01.22
lang: en lang: en
--- ---
General educational game in the broad meaning of this word. When learning programming languages, it is General educational game in the broad meaning of this word. In the process of learning programming languages,
recommended to write your own version first and then use it to demonstrate and test other software or it is recommended to write your own version first and then use it for demonstrating and testing another
hardware. The three-dimensional interface is written in JavaScript Canvas the logic of the game itself software or hardware. The three-dimensional interface is written in JavaScript Canvas the logic of the
is two-dimensional. game itself is two-dimensional. Additional external libraries are not used.
Description of graphics algorithm: [Spinning cube in space]({{ '/en/2023/01/11/spinning-cube-in-space.html' | relative_url }}). Description of graphics algorithm: [Spinning cube in space]({{ '/en/2023/01/11/spinning-cube-in-space.html' | relative_url }}).
{% include heading.html text="Experimental interface" hash="experimental-interface" %} {% include heading.html text="Experimental interface" hash="experimental-interface" %}
Turned off by default you can just play Tetris. In addition to the flat version, two volumetric variants Turned off by default you can just play Tetris. In addition to the two-dimensional version, two volumetric variants
are added: *parallel projection* and *perspective projection* parameters for each of them can be changed. 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 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 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 at a distance, comparable to the size of the playing field. For parallel projection: you can change the
@ -31,24 +31,24 @@ point for rotations — is the central lower far point of the field. For all var
of the cube 32, the size of the square 30 and the indent 2. The origin of coordinates is located at 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. 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, <b>Testing:</b> start the game, collect a certain number of figures on the field, pause the game, and
and switch between the variants of the three-dimensional image, rotate the field with figures, change then switch the variants of the three-dimensional image, rotate the field with figures, change the
the settings and so on. transparency, move the central point and so on.
<b>Controls:</b> keyboard buttons with arrows right, left, up, down and the button `pause`.
{% include volumetric-tetris-en.html -%} {% include volumetric-tetris-en.html -%}
{% include heading.html text="Gaming process" hash="gaming-process" %} {% include heading.html text="Gaming process" hash="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 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 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. 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 <b>Game feature:</b> the collected lines first blink and then disappear meanwhile the
for this time the current figure continues to fall. 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 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 new level, the speed of the figures increases and reaches a maximum at level 21. In snail mode, the speed increase
increases 5 times slower and reaches a maximum at level 104. The current speed is displayed above the playing becomes slower 5 times, and the speed of the figures reaches a maximum at level 104. The current speed is displayed
field as a `meter` indicator. above the playing field as a `meter` indicator.

View file

@ -12,18 +12,19 @@ lang: en
{%- assign articles = "" | split: "" %} {%- assign articles = "" | split: "" %}
{%- assign articles = articles | push: "Volumetric tetris" %} {%- assign articles = articles | push: "Volumetric tetris" %}
{%- capture article_brief %} {%- capture article_brief %}
General educational game in the broad meaning of this word. When learning programming languages, it is General educational game in the broad meaning of this word. In the process of learning programming languages,
recommended to write your own version first and then use it to demonstrate and test other software or it is recommended to write your own version first and then use it for demonstrating and testing another
hardware. The three-dimensional interface is written in JavaScript Canvas the logic of the game itself software or hardware. The three-dimensional interface is written in JavaScript Canvas the logic of the
is two-dimensional. game itself is two-dimensional. Additional external libraries are not used.
{%- endcapture %} {%- endcapture %}
{%- assign articles = articles | push: article_brief %} {%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Spinning spatial cross" %} {%- assign articles = articles | push: "Spinning spatial cross" %}
{%- capture article_brief %} {%- capture article_brief %}
We are writing an algorithm for rotating a three-dimensional figure by an angle around its center along We are writing an algorithm for rotating a three-dimensional figure around its center along all three axes
all three axes at once. In the previous example, we rotated cube in space now there are a lot of cubes, at once. In the previous example, we rotated cube in space in this example, there are a lot of cubes, the
the algorithm is almost the same and we use the same formulas. We draw two variants of the figure: algorithm will be almost the same, and we will use the same formulas. For clarity, let's take two variants
*spatial cross* and *cross-cube* in two types of projections, consider the difference. of a symmetrical volumetric figure in two types of projections *spatial cross* and *cross-cube* we
consider the difference between them.
{%- endcapture %} {%- endcapture %}
{%- assign articles = articles | push: article_brief %} {%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Spinning cube in space" %} {%- assign articles = articles | push: "Spinning cube in space" %}
@ -32,7 +33,7 @@ We consider the difference between parallel and perspective projection. Both are
for various purposes. In the previous example, we rotated square on plane we pass into three-dimensional 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 space. Now, to display the rotation of a three-dimensional object on the screen plane, we first need to
create a *mathematical model* of a three-dimensional object, rotate it by an angle, draw a projection from create a *mathematical model* of a three-dimensional object, rotate it by an angle, draw a projection from
it and display already the projection on the screen. it and display already the projection on the screen. For clarity, we will use the cartesian coordinate system.
{%- endcapture %} {%- endcapture %}
{%- assign articles = articles | push: article_brief %} {%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Spinning square on plane" %} {%- assign articles = articles | push: "Spinning square on plane" %}

View file

@ -111,7 +111,7 @@ function changeTv2(axis, caller) {
function changeDistance2(caller) { function changeDistance2(caller) {
d2=caller.target.valueAsNumber; d2=caller.target.valueAsNumber;
} }
// показать центральную точку // двигать центральную точку
function showCenter(caller) { function showCenter(caller) {
tv2.show=!tv2.show; tv2.show=!tv2.show;
} }
@ -154,7 +154,7 @@ function refreshParams() {
document.getElementById('tv2Z').max = d2/2; document.getElementById('tv2Z').max = d2/2;
document.getElementById('tv2Z').value = tv2.z; document.getElementById('tv2Z').value = tv2.z;
document.getElementById('tv2Zo').value = tv2.z; document.getElementById('tv2Zo').value = tv2.z;
document.getElementById('dist').max = d2*2; document.getElementById('dist').max = d2max;
document.getElementById('dist').value = d2; document.getElementById('dist').value = d2;
document.getElementById('oDist').value = d2; document.getElementById('oDist').value = d2;
refreshDisabled(); refreshDisabled();

View file

@ -37,14 +37,14 @@ const t0 = {}; t0.reCalc = function() {
}; };
t0.reCalc(); t0.reCalc();
// угол поворота игрового поля с кубиками // угол поворота игрового поля с кубиками
let deg={}; deg.setDefault = function() { let deg = {}; deg.setDefault = function() {
this.x=-1; this.x=-1;
this.y=0; this.y=0;
this.z=0; this.z=0;
}; };
deg.setDefault(); deg.setDefault();
// параллельная проекция: центр и экран наблюдателя // параллельная проекция: центр и экран наблюдателя
let d1 = 600, tv1={}; tv1.reCalc = function() { let d1, tv1 = {}; tv1.reCalc = function() {
this.x=columns*(size+gap)/2; this.x=columns*(size+gap)/2;
this.y=(size+gap)*2; this.y=(size+gap)*2;
this.z=(size+gap)*2; this.z=(size+gap)*2;
@ -52,12 +52,12 @@ let d1 = 600, tv1={}; tv1.reCalc = function() {
} }
tv1.reCalc(); tv1.reCalc();
// перспективная проекция: центр и экран наблюдателя // перспективная проекция: центр и экран наблюдателя
let d2 = 600, tv2 = {}; tv2.reCalc = function() { let d2, d2max, tv2 = {}; tv2.reCalc = function() {
this.x = columns*(size+gap)/2; this.x = columns*(size+gap)/2;
this.y = rows*(size+gap)/2; this.y = rows*(size+gap)/2;
this.z = (size+gap)*2; this.z = (size+gap)*2;
this.show=false; this.show=false;
d2 = Math.max(rows,columns)*(size+gap); d2 = Math.max(rows,columns)*(size+gap); d2max = d2*2;
}; };
tv2.reCalc(); tv2.reCalc();
// стакан с игрой // стакан с игрой

View file

@ -34,7 +34,7 @@ alt="&x'=x_0+(x-x_0)cos\varphi-(y-y_0)sin\varphi,&\\&y'=y_0+(x-x_0)sin\varphi+(y
<div> <div>
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
@ -42,7 +42,7 @@ alt="&x'=x_0+(x-x_0)cos\varphi-(y-y_0)sin\varphi,&\\&y'=y_0+(x-x_0)sin\varphi+(y
```html ```html
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
``` ```
@ -115,7 +115,7 @@ document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
<div> <div>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
@ -123,7 +123,7 @@ document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
```html ```html
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
``` ```

View file

@ -1,8 +1,8 @@
--- ---
title: Вращаем куб в пространстве title: Вращаем куб в пространстве
description: Рассматриваем разницу между параллельной и перспективной проекцией. Обе широко используются на практике для различных целей. В предыдущем примере мы вращали... description: Рассмотрим разницу между параллельной и перспективной проекцией. Обе широко используются на практике для различных целей. В предыдущем примере мы вращали...
sections: [Линейная перспектива,Матрица поворота,Экспериментальная модель] sections: [Линейная перспектива,Матрица поворота,Экспериментальная модель]
tags: [javascript,онлайн,canvas,геометрия,графика,изображение,картинка,квадрат,куб] tags: [javascript,онлайн,canvas,геометрия,графика,изображение,картинка,квадрат,куб,3д,трёхмерный]
scripts: [/js/classes-point-cube.js,/js/spinning-cube.js,/js/spinning-cube2.js] scripts: [/js/classes-point-cube.js,/js/spinning-cube.js,/js/spinning-cube2.js]
styles: [/css/pomodoro1.css] styles: [/css/pomodoro1.css]
canonical_url: /ru/2023/01/10/spinning-cube-in-space.html canonical_url: /ru/2023/01/10/spinning-cube-in-space.html
@ -11,12 +11,12 @@ title_translated: Spinning cube in space
date: 2023.01.10 date: 2023.01.10
--- ---
Рассматриваем разницу между параллельной и перспективной проекцией. Обе Рассмотрим разницу между параллельной и перспективной проекцией. Обе широко
широко используются на практике для различных целей. В предыдущем примере мы используются на практике для различных целей. В предыдущем примере мы
[вращали квадрат на плоскости]({{ '/ru/2023/01/05/spinning-square-on-plane.html' | relative_url }}) [вращали квадрат на плоскости]({{ '/ru/2023/01/05/spinning-square-on-plane.html' | relative_url }})
переходим в трёхмерное пространство. Теперь, чтобы отобразить на плоскости экрана поворот трёхмерного переходим в трёхмерное пространство. Теперь, чтобы отобразить на плоскости экрана поворот трёхмерного
объекта, нужно сначала создать *математическую модель* трёхмерного объекта, повернуть её на угол, срисовать объекта, нужно сначала создать *математическую модель* трёхмерного объекта, повернуть её на угол, срисовать
с неё проекцию и отобразить на экране уже проекцию. с неё проекцию и отобразить на экране уже проекцию. Для наглядности будем использовать декартову систему координат.
Усложнённая модель, много кубиков: [Вращаем пространственный крест]({{ '/ru/2023/01/15/spinning-spatial-cross.html' | relative_url }}). Усложнённая модель, много кубиков: [Вращаем пространственный крест]({{ '/ru/2023/01/15/spinning-spatial-cross.html' | relative_url }}).
@ -24,13 +24,13 @@ date: 2023.01.10
<div style="display: flex; flex-direction: column; padding-right: 8px;"> <div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Параллельная проекция</span> <span>Параллельная проекция</span>
<canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
<div style="display: flex; flex-direction: column;"> <div style="display: flex; flex-direction: column;">
<span>Перспективная проекция</span> <span>Перспективная проекция</span>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
</div> </div>
@ -47,11 +47,11 @@ date: 2023.01.10
в середине холста. Ось `X` направлена вправо, ось `Y` направлена вниз, ось `Z` направлена вдаль. в середине холста. Ось `X` направлена вправо, ось `Y` направлена вниз, ось `Z` направлена вдаль.
Выполняется поворот последовательно по всем трём осям: сначала по оси `X`, затем по оси `Y` и затем Выполняется поворот последовательно по всем трём осям: сначала по оси `X`, затем по оси `Y` и затем
по оси `Z`. Настройками модели можно управлять, например можно отключать лишнее вращение по осям и по оси `Z`. Настройками модели можно управлять, например можно отключать лишнее вращение по осям и
изменять положение центра проекции на экране наблюдателя. двигать центральную точку проекции на экране наблюдателя.
<div> <div>
<canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
<form> <form>
@ -91,7 +91,7 @@ date: 2023.01.10
<output name="result">300</output> <output name="result">300</output>
</div> </div>
<div> <div>
<label for="center">Показать центральную точку:</label> <label for="center">Двигать центральную точку:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)"> <input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div> </div>
</form> </form>
@ -151,8 +151,8 @@ alt="{(x-x_1)\over(y-y_1)}={(x_2-x_1)\over(y_2-y_1)}." %}
Сначала обходим вершины куба и поворачиваем их на угол относительно центральной точки. Затем обходим грани Сначала обходим вершины куба и поворачиваем их на угол относительно центральной точки. Затем обходим грани
куба и получаем проекции входящих в них вершин. После этого сортируем проекции граней по удалённости. Затем куба и получаем проекции входящих в них вершин. После этого сортируем проекции граней по удалённости. Затем
рисуем проекции на плоскости соединяем точки линиями. Рисуем полупрозрачным цветом сперва дальние грани и рисуем проекции на плоскости соединяем точки линиями. Рисуем почти прозрачным цветом сперва дальние грани
поверх них ближние, чтобы сквозь ближние грани было видно дальние. и поверх них ближние, чтобы сквозь ближние грани было видно дальние.
На каждом шаге отображения фигуры повторяем сортировку граней по удалённости, так как с изменением На каждом шаге отображения фигуры повторяем сортировку граней по удалённости, так как с изменением
угла поворота, координаты смещаются, и ближние грани становятся дальними. угла поворота, координаты смещаются, и ближние грани становятся дальними.

View file

@ -1,8 +1,8 @@
--- ---
title: Вращаем пространственный крест title: Вращаем пространственный крест
description: Пишем алгоритм для поворота объёмной фигуры на угол вокруг своего центра по всем трём осям сразу. В предыдущем примере мы вращали куб в пространстве... description: Пишем алгоритм для поворота трёхмерной фигуры вокруг своего центра по всем трём осям сразу. В предыдущем примере мы вращали куб в пространстве в этом...
sections: [Объёмные фигуры,Матрица поворота,Экспериментальная модель] sections: [Объёмные фигуры,Матрица поворота,Экспериментальная модель]
tags: [javascript,онлайн,canvas,геометрия,матрица,графика,изображение,картинка,квадрат,куб] tags: [javascript,онлайн,canvas,геометрия,матрица,графика,изображение,картинка,квадрат,куб,3д,трёхмерный]
scripts: [/js/classes-point-cube.js,/js/spinning-spatial-cross.js,/js/spinning-spatial-cross2.js] scripts: [/js/classes-point-cube.js,/js/spinning-spatial-cross.js,/js/spinning-spatial-cross2.js]
styles: [/css/pomodoro1.css] styles: [/css/pomodoro1.css]
canonical_url: /ru/2023/01/15/spinning-spatial-cross.html canonical_url: /ru/2023/01/15/spinning-spatial-cross.html
@ -11,10 +11,11 @@ title_translated: Spinning spatial cross
date: 2023.01.15 date: 2023.01.15
--- ---
Пишем алгоритм для поворота объёмной фигуры на угол вокруг своего центра по всем трём осям сразу. В предыдущем Пишем алгоритм для поворота трёхмерной фигуры вокруг своего центра по всем трём осям сразу. В предыдущем
примере мы [вращали куб в пространстве]({{ '/ru/2023/01/10/spinning-cube-in-space.html' | relative_url }}) примере мы [вращали куб в пространстве]({{ '/ru/2023/01/10/spinning-cube-in-space.html' | relative_url }})
теперь кубиков будет много, алгоритм будет почти такой же и формулы будем использовать те же. Рисуем два в этом примере кубиков будет много, алгоритм будет почти такой же, и формулы будем использовать те же. Для
варианта фигуры: *пространственный крест* и *крест-куб* в двух типах проекций, рассматриваем разницу. наглядности возьмём два варианта симметричной объёмной фигуры в двух типах проекций *пространственный крест*
и *крест-куб* рассматриваем разницу между ними.
Тестирование экспериментального интерфейса: [Объёмный тетрис]({{ '/ru/2023/01/21/volumetric-tetris.html' | relative_url }}). Тестирование экспериментального интерфейса: [Объёмный тетрис]({{ '/ru/2023/01/21/volumetric-tetris.html' | relative_url }}).
@ -24,13 +25,13 @@ date: 2023.01.15
<div style="display: flex; flex-direction: column; padding-right: 8px;"> <div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Параллельная проекция</span> <span>Параллельная проекция</span>
<canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas1" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
<div style="display: flex; flex-direction: column;"> <div style="display: flex; flex-direction: column;">
<span>Перспективная проекция</span> <span>Перспективная проекция</span>
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
</div> </div>
@ -41,13 +42,13 @@ date: 2023.01.15
<div style="display: flex; flex-direction: column; padding-right: 8px;"> <div style="display: flex; flex-direction: column; padding-right: 8px;">
<span>Параллельная проекция</span> <span>Параллельная проекция</span>
<canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas3" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
<div style="display: flex; flex-direction: column;"> <div style="display: flex; flex-direction: column;">
<span>Перспективная проекция</span> <span>Перспективная проекция</span>
<canvas id="canvas4" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas4" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
</div> </div>
@ -60,11 +61,11 @@ date: 2023.01.15
Слегка усложнённая версия из предыдущего примера теперь кубиков много. В дополнение к предыдущим настройкам Слегка усложнённая версия из предыдущего примера теперь кубиков много. В дополнение к предыдущим настройкам
можно поменять: вариант фигуры *пространственный крест* или *крест-куб*, направление сортировки граней можно поменять: вариант фигуры *пространственный крест* или *крест-куб*, направление сортировки граней
*линейная перспектива* или *обратная перспектива* и прозрачность стенок кубиков. *прямая перспектива* или *обратная перспектива* и прозрачность стенок кубиков.
<div> <div>
<canvas id="canvas5" width="300" height="300" style="border: 1px solid gray;"> <canvas id="canvas5" width="300" height="300" style="border: 1px solid gray;">
<p>Ваш браузер не поддерживает Canvas</p> <p>Холст для отображения результатов вычислений</p>
</canvas> </canvas>
</div> </div>
<div> <div>
@ -105,7 +106,7 @@ date: 2023.01.15
<output name="result">300</output> <output name="result">300</output>
</div> </div>
<div> <div>
<label for="center">Показать центральную точку:</label> <label for="center">Двигать центральную точку:</label>
<input type="checkbox" id="center" name="center" oninput="showCenter(event)"> <input type="checkbox" id="center" name="center" oninput="showCenter(event)">
</div> </div>
<span>Прозрачность кубиков:</span> <span>Прозрачность кубиков:</span>
@ -123,10 +124,10 @@ date: 2023.01.15
<input type="radio" id="second" name="figure" value="second" checked> <input type="radio" id="second" name="figure" value="second" checked>
<label for="second">Куб</label> <label for="second">Куб</label>
</form> </form>
<span>Перспективная проекция:</span> <span>Линейная перспектива:</span>
<form oninput="changeOrder(event)"> <form oninput="changeOrder(event)">
<input type="radio" id="linear" name="order" value="linear" checked> <input type="radio" id="linear" name="order" value="linear" checked>
<label for="linear">Линейная</label> <label for="linear">Прямая</label>
<input type="radio" id="reverse" name="order" value="reverse"> <input type="radio" id="reverse" name="order" value="reverse">
<label for="reverse">Обратная</label> <label for="reverse">Обратная</label>
</form> </form>
@ -134,12 +135,13 @@ date: 2023.01.15
{% include heading.html text="Описание алгоритма" hash="algorithm-description" %} {% include heading.html text="Описание алгоритма" hash="algorithm-description" %}
Подготавливаем матрицу из нулей и единиц, где единица означает кубик в определенном месте фигуры. Затем Подготавливаем трёхмерную матрицу из нулей и единиц, где единица означает кубик в определенном месте фигуры.
обходим эту матрицу и заполняем массив кубиков с соответствующими координатами вершин. После этого запускаем Затем обходим эту матрицу и заполняем массив кубиков с соответствующими координатами вершин. После этого
вращение по всем трём осям сразу. На каждом шаге обходим массив кубиков и получаем проекции их граней. Затем запускаем вращение по всем трём осям сразу. На каждом шаге обходим массив кубиков и получаем проекции их
сортируем массив граней по удалённости от центра проекции, обходим этот массив и выкидываем из него одинаковые граней. Затем сортируем массив граней по удалённости от центра проекции, обходим этот массив и выкидываем
пары это есть смежные стенки между соседними кубиками внутри фигуры. После этого полупрозрачным цветом рисуем из него одинаковые пары это есть смежные стенки между соседними кубиками внутри фигуры. После этого
грани кубиков сначала дальние и затем ближние, чтобы через ближние грани было видно дальние. рисуем полупрозрачным цветом грани кубиков сначала дальние, а затем ближние, чтобы через ближние грани
было видно дальние.
{% include heading.html text="Реализация на JavaScript" hash="implementation-in-javascript" %} {% include heading.html text="Реализация на JavaScript" hash="implementation-in-javascript" %}

View file

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

View file

@ -11,26 +11,27 @@ title_translated: Code with comments
{%- assign articles = "" | split: "" %} {%- assign articles = "" | split: "" %}
{%- assign articles = articles | push: "Объёмный тетрис" %} {%- assign articles = articles | push: "Объёмный тетрис" %}
{%- capture article_brief %} {%- capture article_brief %}
Общеобразовательная игра в широком смысле этого слова. При изучении языков программирования рекомендуется Общеобразовательная игра в широком смысле этого слова. В процессе изучения языков программирования
сначала написать свою версию и потом использовать её для демонстрации и тестирования другого программного рекомендуется сначала написать свою версию и потом использовать её для демонстрации и тестирования
обеспечения или оборудования. Трёхмерный интерфейс написан на JavaScript Canvas логика самой игры двухмерная. другого программного обеспечения или оборудования. Трёхмерный интерфейс написан на JavaScript Canvas
логика самой игры двухмерная. Дополнительные внешние библиотеки не используются.
{%- endcapture %} {%- endcapture %}
{%- assign articles = articles | push: article_brief %} {%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Вращаем пространственный крест" %} {%- assign articles = articles | push: "Вращаем пространственный крест" %}
{%- capture article_brief %} {%- capture article_brief %}
Пишем алгоритм для поворота объёмной фигуры на угол вокруг своего центра по всем трём осям сразу. В Пишем алгоритм для поворота трёхмерной фигуры вокруг своего центра по всем трём осям сразу. В предыдущем
предыдущем примере мы вращали куб в пространстве теперь кубиков будет много, алгоритм будет почти примере мы вращали куб в пространстве в этом примере кубиков будет много, алгоритм будет почти такой
такой же и формулы будем использовать те же. Рисуем два варианта фигуры: *пространственный крест* и же, и формулы будем использовать те же. Для наглядности возьмём два варианта симметричной объёмной фигуры
*крест-куб* в двух типах проекций, рассматриваем разницу. в двух типах проекций *пространственный крест* и *крест-куб* рассматриваем разницу между ними.
{%- endcapture %} {%- endcapture %}
{%- assign articles = articles | push: article_brief %} {%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Вращаем куб в пространстве" %} {%- assign articles = articles | push: "Вращаем куб в пространстве" %}
{%- capture article_brief %} {%- capture article_brief %}
Рассматриваем разницу между параллельной и перспективной проекцией. Обе широко используются на практике Рассмотрим разницу между параллельной и перспективной проекцией. Обе широко используются на практике
для различных целей. В предыдущем примере мы вращали квадрат на плоскости переходим в трёхмерное для различных целей. В предыдущем примере мы вращали квадрат на плоскости переходим в трёхмерное
пространство. Теперь, чтобы отобразить на плоскости экрана поворот трёхмерного объекта, нужно сначала пространство. Теперь, чтобы отобразить на плоскости экрана поворот трёхмерного объекта, нужно сначала
создать *математическую модель* трёхмерного объекта, повернуть её на угол, срисовать с неё проекцию и создать *математическую модель* трёхмерного объекта, повернуть её на угол, срисовать с неё проекцию
отобразить на экране уже проекцию. и отобразить на экране уже проекцию. Для наглядности будем использовать декартову систему координат.
{%- endcapture %} {%- endcapture %}
{%- assign articles = articles | push: article_brief %} {%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Вращаем квадрат на плоскости" %} {%- assign articles = articles | push: "Вращаем квадрат на плоскости" %}

View file

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

View file

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