(Мой первый проход был сложным выводом естественной кажущейся формулы для этого. Но потом я понял, что есть гораздо, гораздо лучшее решение. Я бы вспомнил это раньше, если бы использовал Комплексный анализ в последние 20 лет..)
Правильный способ сделать это - применить интегральную формулу Коши .При этом вы можете сопоставить любой многоугольник с любым другим многоугольником.Если многоугольники не пересекаются сам по себе, он отправит границу к границе, а внутренность - внутрь.Отображение также обладает превосходным свойством, что оно конформно , что означает, что углы сохраняются.Под этим я подразумеваю, что если пара кривых пересекается в вашем регионе, то они будут сопоставлены с парой кривых, которые пересекаются под тем же углом.(Многие из рисунков Эшера основаны на конформных отображениях.)
Достаточно шумихи.Как ты делаешь это?Я объясню это, предполагая, что вы абсолютно ничего не знаете о сложном анализе.Я буду использовать некоторые термины исчисления, но вы сможете следовать моим указаниям, даже если вы вообще не знаете исчисления.Поскольку я предполагаю, что так мало, объяснение должно быть довольно длинным.Я прошу прощения за это.
Каждая точка (x, y)
в реальной плоскости может рассматриваться как комплексное число z = x + iy
.Мы можем сложить и умножить комплексные числа, используя обычные правила алгебры и тот факт, что i * i = -1
.Кроме того, обратите внимание, что 1 = (x + iy) * (x - iy)/(x<sup>2</sup> + y<sup>2</sup>)
, поэтому мы можем делить, если мы допустим 1/z = (x - iy)/(x<sup>2</sup> + y<sup>2</sup>)
Поэтому у нас есть все обычные правила арифметики.
Но мы можем добиться большего, чем это.Мы можем сделать исчисление.В частности, мы можем сделать интегралы по траекториям вокруг кривых.Интеграл от функции вдоль кривой является своего рода средневзвешенным значением этой функции по точкам на этой кривой.Вы можете прочитать о том, как это сделать в целом.Но вот как это сделать в этом случае.
Предположим, что начальная область имеет углы P<sub>1</sub>, P<sub>2</sub>, P<sub>3</sub>, P<sub>4</sub>
.Путь вокруг области определяется четырьмя отрезками (P<sub>1</sub>, P<sub>2</sub>), (P<sub>2</sub>, P<sub>3</sub>), (P<sub>3</sub>, P<sub>4</sub>), (P<sub>4</sub>, P<sub>1</sub>)
.Я расскажу о том, как обрабатывать первый отрезок.Остальные похожи.
Интеграл пути от f(z)
по (P<sub>1</sub>, P<sub>2</sub>)
- это интеграл от 0 до 1 из f((1-s)P<sub>1</sub> + sP<sub>2</sub>)(P<sub>2</sub> - P<sub>1</sub>)
.Чтобы оценить этот интеграл, проще всего сделать числовую интеграцию, используя правило Симпсона .Для этого выберите нечетное число n
и для значений s = 0, 1/n, 2/n, ..., (n-1)/n, 1
присвойте им весовые коэффициенты в шаблоне 1, 4, 2, 4, 2, ..., 2, 4, 1
.(Конечные точки - 1, все остальное чередуется между 4 и 2.) Теперь для каждой точки вычислите f((1-s)P<sub>1</sub> + sP<sub>2</sub>)(P<sub>2</sub> - P<sub>1</sub>)
, умножьте на вес и сложите их все вместе.Затем разделите на магическое значение 3 * (n-1)
.Результат примерно ваш интеграл.(По мере роста n
ошибка в этом приближении составляет O(1/n<sup>4</sup>)
. В вашем случае, если вы возьмете n = 21
, то приближение должно получиться достаточно хорошим, чтобы отобразить пиксели на нужный пиксель, за исключением некоторых пикселей вблизи границы.Сделайте его немного больше, и проблемная область уменьшится. По краю вам понадобится кратное число пикселей на стороне, чтобы уменьшить ошибку.)
ОК, так что мы можемсделать интегралы по путям.Какова ценность этого?Хорошо, предположим, что мы берем случайную точку z<sub>0</sub> = x + iy
где-нибудь в нашем регионе.Предположим, что f(z)
определено на пути.Тогда Интегральная формула Коши говорит, что интеграл вокруг нашей области (который является суммой 4-х кусочных интегралов, которые мы знаем, как сделать) из f(z)/(2 * π * i * (z - z<sub>0</sub>))
- это действительно хорошая функция, которая будет соответствовать нашей оригинальнойфункция на границе.Я не буду вдаваться во все «действительно приятные» вещи об этом, но то, что я говорил выше о конформных , является частью этого.
Теперь, какую функцию f
делаем мыиспользовать?Хорошо предположим, что наш регион отображается на регион с углами Q<sub>1</sub>, Q<sub>2</sub>, Q<sub>3</sub>, Q<sub>4</sub>
.Мы хотим, чтобы первый фрагмент пути отображался на второй фрагмент пути.Поэтому мы хотим, чтобы f((1-s)P<sub>1</sub> + sP<sub>2</sub>)
было (1-s)Q<sub>1</sub> + sQ<sub>2</sub>
.Это говорит нам о том, как вычислить f
во всех точках, которые нам нужны для нашего интеграла.
Теперь вы спросите, как вы можете изменить это?Это простоПросто поменяйте местами роль двух полигонов и рассчитайте обратное преобразование!Что приносит действительно хороший юнит-тест.Вы должны определить пару странных областей, выбрать точку посередине и убедиться, что, если вы переходите от первого к второму и обратно, вы попадаете близко к тому, с чего начали.Если вы пройдете этот тест, то, вероятно, вы не ошиблись.
И, наконец, как насчет моего общего заявления о полигоне, которое я сделал?Ну, мы определили наш путь как четыре части, которые мы прошли линейно.У многоугольника более высокой степени просто больше фигур на своем пути, но в остальном вычисление выполняется точно так же.