БлогNot. Полярные цветы

Полярные цветы

Если вы ничего не слышали о полярных координатах, обязательно познакомьтесь с ними. Полярные координаты можно применять не только для того, о чём написано в "Вики", но и просто для лёгкого генерирования красивых математических картинок, причём, замечательно закономерных, а не каких-то там рандомных.

Всё, что нам понадобится - придумать зависимость полярного радиуса r от полярного угла fi, организовать цикл по значениям полярного угла от 0 до 360 градусов с малым шагом и нарисовать "по точкам" картинку, например, такую:

картинка 1
картинка 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
картинка 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
картинка 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 [2986 просмотров]


теги: javascript цвет графика php математика

показать комментарии (1)