Полярные цветы
Если вы ничего не слышали о полярных координатах, обязательно познакомьтесь с ними. Полярные координаты можно применять не только для того, о чём написано в "Вики", но и просто для лёгкого генерирования красивых математических картинок, причём, замечательно закономерных, а не каких-то там рандомных.
Всё, что нам понадобится - придумать зависимость полярного радиуса r
от полярного угла fi
, организовать цикл по значениям полярного угла от 0 до 360 градусов с малым шагом и нарисовать "по точкам" картинку, например, такую:
картинка 1
На переход цвета можно пока внимания не обращать, он делается отдельно подготовленным градиентом и независимо от контура фигуры, а вот помнить, как полярные координаты переводятся в обычные декартовы, нужно - ведь рисовать-то мы будем в декартовой системе координат:
x = r * cos(fi) y = r * sin(fi)
Учтём также, что зависимость r(fi)
должна быть не "любой", а периодической, связанной с синусами и косинусами, графики которых в полярной системе координат представляют собой окружности.
Скажем, картинка 1 получена зависимостью, которую на яваскрипте можно описать формулой
r = size * (1.2 + 0.9 * Math.cos(1.8 * fi) + 0.1 * Math.cos(0.9 * fi));
с аргументом "масштаб" (size
), равным 140 (см. комментарии 1) и 2) в приложенном листинге).
Публикуемый листинг рисует другую картинку, вот такую (сохранена в JPEG со средним качеством, а то что-то файл большой получается в PNG):
картинка 2
Код можно сохранить как файл типа .html
в кодировке UTF-8 (Юникод) и запустить на своём компьютере, ну а масштаб рисунка и формулу посмотрите в тексте программы сами :)
Также приветствуется присылание красивых зависимостей r(fi)
, найденных вами.
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>Polar Flowers</title> </head> <body> <canvas id="canvas">Извините, Ваш браузер не поддерживает тег canvas</canvas><br> <script type="text/javascript"> //Получить канву и растянуть её по размерам окна: var canvas = document.getElementById("canvas"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; //Получить контекст и очистить канву: var ctx = canvas.getContext("2d"); ctx.clearRect (0, 0, canvas.width, canvas.height); //Вызвать метод отрисовки с аргументами "центр по Ox", "центр по Oy", "масштаб": makePicture (Math.floor(window.innerWidth/2), Math.floor(window.innerHeight/2), 6); //1) Масштаб может изменяться в довольно широких пределах! function makePicture (centerX, centerY, size) { //Метод отрисовки var x = 0, y = 0; //декартовы координаты var r, fi = 0; //полярные координаты //Градиент для отрисовки: var gradient = ctx.createLinearGradient (0, 0, canvas.width, canvas.height); gradient.addColorStop("0.25","red"); gradient.addColorStop("0.50","green"); gradient.addColorStop("0.75","blue"); ctx.strokeStyle=gradient; //Начать формировать картинку: ctx.beginPath(); for (fi = 0.; fi<= 360.; fi+=0.01) { //Цикл по полярному углу //2) Основная формула, зависимость r(fi): r = size * ( 4 + Math.sin(6 * fi) + //6 лепестков 0.25 * Math.sin(60 * fi) + 0.25 * Math.sin(40 * fi) ) * (1 + fi/35); //в формуле можно "баловаться" с коэффициентами //Перевод из полярных координат в декартовы: x = Math.floor (r * Math.cos(fi)) + centerX; y = Math.floor (r * Math.sin(fi)) + centerY; //На первом шаге поставить перо в центр: if (fi == 0) ctx.moveTo(x, y); //Потом запомнить очередную линию: ctx.lineTo(x, y); } //Нарисовать это: ctx.stroke(); } </script> <noscript><div>Извините, требуется включённый Javascript для работы приложения!</div></noscript> </body></html>
Вот эта симпатичная картинка (сохранена также со средним качеством) получена с помощью формулы
r = size * ( 0.15*Math.cos(20*fi) + 0.15*Math.sin(20*fi) + 1.2*Math.atan(fi/30));
при аргументе size
функции makePicture
, равном 150.
картинка 3
Ниже показан подобный же скрипт на PHP, его можно выполнить, например, установив на компьютере Denwer или другой локальный хост. Рисует фигуру, определённую отдельной функцией и закрашивает двухцветным градиентом от левого верхнего угла
<?php function recalc ($x, $a, $b, $c, $d) { //Пересчитать x из интервала [a,b] в y из интервала [c,d] $y = round($c + ($x-$a) * ($d-$c) / ($b-$a)); return max(0,min($y,255)); //не менее 0 и не более 255 } function gradColor($row,$col,$width,$height,$color1,$color2) { //Получить новый цвет RGB для точки ($row,$col) и //размера картинки ($width,$height) между $color1 и $color2 $diag = sqrt(pow($width-1,2)+pow($height-1,2)); $d = sqrt(pow($row,2)+pow($col,2)); list($r1, $g1, $b1) = sscanf($color1, "#%02x%02x%02x"); list($r2, $g2, $b2) = sscanf($color2, "#%02x%02x%02x"); $r = recalc ($d,0,$diag,$r1,$r2); $g = recalc ($d,0,$diag,$g1,$g2); $b = recalc ($d,0,$diag,$b1,$b2); return array('r'=>$r,'g'=>$g,'b'=>$b); } function draw ($width,$height,$size,$func,$color1,$color2) { //Создать новый узор. Аргументы: //ширина и высота картинки, масштаб, функция, цвет1, цвет2 $img = imagecreatetruecolor($width, $height); imagefill($img,0,0,imagecolorallocate($img,255,255,255)); $cx = floor($width/2); $cy = floor($height/2); $x = $x0 = $y = $y0 = 0; $void = true; for ($fi = 0.; $fi<= 360.; $fi+=0.005) { $r = $size * $func($fi); $x = floor ($r * cos($fi)) + $cx; $y = floor ($r * sin($fi)) + $cy; if ($void){ $x0 = $x; $y0 = $y; $void = false; } $clr = gradColor ($x, $y, $width, $height, $color1, $color2); $color=imagecolorallocate($img, $clr['r'], $clr['g'], $clr['b']); imageline ($img, $x0, $y0, $x, $y, $color); $x0 = $x; $y0 = $y; } header('Content-Type: image/png'); imagejpeg($img); imagedestroy($img); } //Рисунок по формуле draw1: draw (600,600,160,'draw1','#ff0000','#0066ff'); //Рисунок по формуле draw2: //draw (600,600,800,'draw2','#ff0000','#0099ff'); function draw1 ($fi) { //Конкретная функция для зависимости $r($fi) return 0.9 + 0.8 * cos(1.8 * $fi) + 0.1 * cos(0.9 * $fi); } function draw2 ($fi) { //Конкретная функция для зависимости $r($fi) return 0.25*sin(0.125*$fi/32) + 0.25*cos(0.125*$fi/32); //попробуйте поменять числовые коэффициенты } ?>
23.01.2018, 22:57 [3176 просмотров]