1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-18 06:21:26 +02:00

ru-RU translation (#295)

* ru-RU introduction

Translation of introduction to Russian

* ru-RU whatis

Translation of chapter 2 to Russian

* (fixup) ru-RU intro

fixed missing translations

* ru-RU index.html

Translated header, meta, title and link names for existing chapter's traslations. (will be updated with every new commit)

* ru-RU locale strings

Locale string russian traslations

* locale fixup

* build chapters 1,2

* ru-RU explanation

translation of explanation to Russian.

* ru-RU control

translation of #control to Russian

* ru-RU weightcontrol

translation of #weightcontrol to Russian

* ru-RU derivatives

translation of #derivatives to Russian

* (fixup) ru-RU weightcontrol

* (fixup) ru-RU explanation

* ru-RU extended

Co-authored-by: Mammoth <echo@mammothnotes.com>
This commit is contained in:
ra30r
2021-01-10 13:24:47 -06:00
committed by GitHub
parent 7768431058
commit 402e4fbb03
5 changed files with 515 additions and 0 deletions

View File

@@ -0,0 +1,175 @@
# Математика под кривыми Безье
Кривые Безье по своей форме представляют собой параметрические функции. С точки зрения математики, эти функции хитрят, поскольку разнятся с каноническим определением функции. Последнее есть преобразованием любого количества вводных в <strong>единый</strong> результат. Как бы мы не меняли вводные значения переменных, на выходе всегда получим одно значение.
Параметрические функции хитрят, потому как говоря: "что ж, ладно, нам нужно произвести более одного вывода", заключают, попросту: "давайте использовать более одной функции". Проиллюстрируем: представьте что есть функция, которая преобразует вводную, назовем ее <i>x</i>, в другое значение следуя определенной логике
\[
f(x) = \cos(x)
\]
Нотация <i>f(x)</i> есть стандартным способом записи функции (по конвенции, <i>f</i>, когда представлена всего одна) и ее вывод меняется в зависимости от значения одной переменной (в данном случае, <i>x</i>). Так, изменив <i>x</i> и получим другой результат <i>f(x)</i>.
Пока все логично. Теперь, давайте рассмотрим параметрические функции в действии и разберемся в чем их фокус. И, для начала, примите ко внимаю следующий пример:
\[
\begin{matrix}
f(a) = \cos(a) \\
f(b) = \sin(b)
\end{matrix}
\]
Итак, нам представлены две функции. Ничего особо выдающегося: просто функции синуса и косинуса. Отметим, что, как вы можете видеть, вводные переменные разные. Затем, меняя значение <i>a</i>, мы не влияем на вывод <i>f(b)</i>, поскольку <i>a</i> никак не задействована в этой функции. Параметрические функции хитрят именно с этим: весь набор функций вывода делит между собой одну или более переменную вводную. Как здесь:
\[
\left \{ \begin{matrix}
f_a(t) = \cos(t) \\
f_b(t) = \sin(t)
\end{matrix} \right.
\]
Что же, несколько функций, и всего одна вводная. Меняя значение <i>t</i> — меняем вывод обеих ф-ций, <i>f<sub>a</sub>(t)</i> и <i>f<sub>b</sub>(t)</i>. Возможно вы спросите: "в чем же польза?". Ответ прост и очевиден, если уточнить, что мы имеем ввиду под записью наших функций:
\[
\left \{ \begin{matrix}
x = \cos(t) \\
y = \sin(t)
\end{matrix} \right.
\]
Так-то. Координаты <i>x</i>/<i>y</i>. Связанные мистическим значением <i>t</i>.
Таким образом, мы видим, что параметрические функции не определяют значение <i>y</i> через значение <i>x</i>, как обычные ф-ции, вместо этого они выводят и <i>x</i> и <i>y</i> из мистического значения <i>t</i>. Значит, для каждого значения <i>t</i>, существуют два соответствующих значения <i>x</i> и <i>y</i>, которые мы можем использовать для зарисовки кривой на графике. К примеру, приведенная выше параметрическая функция выводит координаты точки на круге: можно подставить любое значение <i>t</i> (от негативной до позитивной бесконечности), и на выводе мы всегда получим координаты точки на круге с центром в (0,0) и радиусом в 1. Зарисовав точки для <i>t</i> от 0 до 5, получаем следующее:
<graphics-element title=" (Часть) круга: x=sin(t), y=cos(t)" src="./circle.js">
<input type="range" min="0" max="10" step="0.1" value="5" class="slide-control">
</graphics-element>
Кривые Безье — всего один из многих классов параметрических функций. Их главной характеристикой есть использование одной и той же базовой функции для генерации всех выводов. До сих пор, в использованном нами примере, мы производили значения <i>x</i> и <i>y</i> с помощью разных функций (ф-цией синуса и ф-цией косинуса); Безье же использует единый "биноминальный полином" для вывода обоих значений. Но что же такое "биноминальный полином"?
Возможно, вы помните полиномы из школьной программы. Они выглядят следующим образом:
\[
f(x) = a \cdot x^3 + b \cdot x^2 + c \cdot x + d
\]
Так, если наивысшая степень в уравнении составляет <i></i>, мы называем такой полином кубическим, если <i></i> — квадратным. Если это только <i></i> — значит это просто линия (когда же <i>x</i> не упоминается вовсе — это не полином!).
Кривые Безье являются полиномом <i>t</i> (вместо <i>x</i>), где значение <i>t</i> — варъируется между 0 и 1, и коэффициентами <i>a</i>, <i>b</i> и т.д. принимающими "биноминальную" форму. Звучит сложно, но на практике выглядит понятнее:
\[
\begin{aligned}
линейный &= (1-t) + t \\
квадратный &= (1-t)^2 + 2 \cdot (1-t) \cdot t + t^2 \\
кубический &= (1-t)^3 + 3 \cdot (1-t)^2 \cdot t + 3 \cdot (1-t) \cdot t^2 + t^3
\end{aligned}
\]
Я знаю что вы думаете: это не выглядит таким уж простым. Но если мы уберем <i>t</i> и вместо этого поставим *1, внезапно, все становится ясно. Примите ко внимаю такие биномиальные термины:
\[
\begin{aligned}
линийный &= \hspace{2.5em} 1 + 1 \\
квадратый &= \hspace{1.7em} 1 + 2 + 1\\
кубический &= \hspace{0.85em} 1 + 3 + 3 + 1\\
квартический &= 1 + 4 + 6 + 4 + 1
\end{aligned}
\]
Обратите внимание, что 2 это то же, что 1+1, и 3 это 2+1 и 1+2 и 6 это 3+3... Как вы можете видеть, каждый раз поднимаясь на одно разрешение выше, мы начинаем и заканчиваем с единицы, а все промежуточные значения равны суме двух значений над ними в предыдущей строке. Так получаем последовательность цифр, называемой [треугольником Паскаля](https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%B8%D0%BA_%D0%9F%D0%B0%D1%81%D0%BA%D0%B0%D0%BB%D1%8F) (*в оригинале [другая ссылка](https://en.wikipedia.org/wiki/Pascal%27s_triangle) ).
Так-же существует простой способ для выяснения подоплотной работы полиноминальных терминов: если мы переименуем <i>(1-t)</i> в <i>a</i> и <i>t</i> в <i>b</i>, убрав "веса", получим следующее:
\[
\begin{aligned}
линийный &= BLUE[a] + RED[b] \\
квадратый &= BLUE[a] \cdot BLUE[a] + BLUE[a] \cdot RED[b] + RED[b] \cdot RED[b] \\
кубический &= BLUE[a] \cdot BLUE[a] \cdot BLUE[a] + BLUE[a] \cdot BLUE[a] \cdot RED[b] + BLUE[a] \cdot RED[b] \cdot RED[b] + RED[b] \cdot RED[b] \cdot RED[b]\\
\end{aligned}
\]
В целом это просто сума "каждого сочетания <i>a</i> и <i>b</i>", получаемая прогрессивной заменой <i>a</i> на <i>b</i> по ходу уравнения. Потому, это так-же довольно просто. Итак теперь вы знаете что такое биноминальные полиномы. Для полноты картины, ниже привожу их общую функцию:
\[
Bézier(n,t) = \sum_{i=0}^{n}
\underset{биноминальный~термин}{\underbrace{\binom{n}{i}}}
\cdot\
\underset{полиноминальный~термин}{\underbrace{(1-t)^{n-i} \cdot t^{i}}}
\]
И теперь, это полное объяснение. Σ в этой функции означает, что это серия сум (с использованием переменной приведенной под Σ, со стартовым значением в ...=&lt;value&gt; и максимальным значением представленным над Σ)
<div class="howtocode">
### Имплементация базовых функций
Наивно, мы могли бы воплотить базис этой функции как математическую конструкцию, используя функцию как путеводитель:
```
function Bezier(n,t):
sum = 0
for(k=0; k<n; k++):
sum += n!/(k!*(n-k)!) * (1-t)^(n-k) * t^(k)
return sum
```
Я говорю "мы могли бы", поскольку это не входит в наши планы: факторные функции *невероятно* дорого стоят. И, как мы можем понять из выше приведенного текста, треугольник Паскаля можно получить и без таких ухищрений: попросту начнем с [1], далее [1,1], затем [1,2,1], потом [1,3,3,1] и т.д., с каждым новым рядком, записывая на 1 цифру больше, чем в предыдущем, начиная и заканчивая с единицы, а промежуточные цифры определяя суммируя две над ними в предыдущем рядке.
Такой ряд можно сгенерировать предельно быстро, и с этим нам не придется компилировать биноминальные термины, поскольку можно пользоваться значениями из таблицы:
```
lut = [ [1], // n=0
[1,1], // n=1
[1,2,1], // n=2
[1,3,3,1], // n=3
[1,4,6,4,1], // n=4
[1,5,10,10,5,1], // n=5
[1,6,15,20,15,6,1]] // n=6
function binomial(n,k):
while(n >= lut.length):
s = lut.length
nextRow = new array(size=s+1)
nextRow[0] = 1
for(i=1, prev=s-1; i<s; i++):
nextRow[i] = lut[prev][i-1] + lut[prev][i]
nextRow[s] = 1
lut.add(nextRow)
return lut[n][k]
```
Итак, что же здесь происходит? Сначала мы декларируем таблицу достаточного размера для удовлетворения большинства запросов. Далее мы заявляем функцию вывода необходимого значения, вытаскивая его из таблицы, предварительно убедившись, что значения для запрашиваемых <i>n/k</i> присутствуют в наборе и расширяя набор по необходимости (если не присутствуют). Наша базовая функция теперь выглядит типа этого:
```
function Bezier(n,t):
sum = 0
for(k=0; k<=n; k++):
sum += binomial(n,k) * (1-t)^(n-k) * t^(k)
return sum
```
Отлично. Конечно, мы можем оптимизировать ее и далее. Для большинства задач компьютерной графики нам не потребуются кривые произвольного порядка (хотя мы приводим код для произвольных кривых в этом пособии); зачастую нам нужны квадратные и кубические кривые, а это значит, мы можем значительно упростить весь наш код:
```
function Bezier(2,t):
t2 = t * t
mt = 1-t
mt2 = mt * mt
return mt2 + 2*mt*t + t2
function Bezier(3,t):
t2 = t * t
t3 = t2 * t
mt = 1-t
mt2 = mt * mt
mt3 = mt2 * mt
return mt3 + 3*mt2*t + 3*mt*t2 + t3
```
И вот теперь мы знаем как программировать базовую функцию. Превосходно.
</div>
Итак, зная как выглядят базовые функции, время добавить магию делающую кривые Безье такими особенными: контрольные точки.