Almt : другие произведения.

7 красных линий: модель ноября 2014 года

Самиздат: [Регистрация] [Найти] [Рейтинги] [Обсуждения] [Новинки] [Обзоры] [Помощь|Техвопросы]
Ссылки:
Школа кожевенного мастерства: сумки, ремни своими руками
 Ваша оценка:
  • Аннотация:
    Технофанфик на известный рассказ "7 красных линий"

  Постановка задачи "Нарисовать 7 красных линий перпендикулярных друг-другу, где одна линия имеет форму котёнка" выглядит абсурдной только на первый взгляд.
  
  Совершенно очевидно, что задача имеет тривиальное решение при использовании пространства нужной размерности.
  
  Так 1 линия - это 1 измерение. Однако "котёнок" является двумерным изображением, следовательно, для полноценного решения задачи необходимо использовать 8-ми мерное пространство.
  
  Векторное изображение котёнка:
  $catDots = array(
  array(0,1979,771,0,0,0,0,0),
  array(0,2290,725,0,0,0,0,0),
  array(0,2865,944,0,0,0,0,0),
  array(0,3325,1254,0,0,0,0,0),
  array(0,3659,1082,0,0,0,0,0),
  array(0,4096,1070,0,0,0,0,0),
  array(0,4533,311,0,0,0,0,0),
  array(0,4832,92,0,0,0,0,0),
  array(0,4981,69,0,0,0,0,0),
  array(0,5062,0,0,0,0,0,0),
  array(0,5223,253,0,0,0,0,0),
  array(0,5603,564,0,0,0,0,0),
  array(0,5787,990,0,0,0,0,0),
  array(0,5856,1473,0,0,0,0,0),
  array(0,6005,2174,0,0,0,0,0),
  array(0,6063,2531,0,0,0,0,0),
  array(0,6109,2842,0,0,0,0,0),
  array(0,6350,3106,0,0,0,0,0),
  array(0,6040,3497,0,0,0,0,0),
  array(0,5557,3842,0,0,0,0,0),
  array(0,4901,4084,0,0,0,0,0),
  array(0,4763,3624,0,0,0,0,0),
  array(0,4671,3808,0,0,0,0,0),
  array(0,4510,3819,0,0,0,0,0),
  array(0,4372,3739,0,0,0,0,0),
  array(0,4222,3647,0,0,0,0,0),
  array(0,4176,3727,0,0,0,0,0),
  array(0,4130,3612,0,0,0,0,0),
  array(0,4372,3509,0,0,0,0,0),
  array(0,4567,3543,0,0,0,0,0),
  array(0,4544,3612,0,0,0,0,0),
  array(0,4464,3670,0,0,0,0,0),
  array(0,4406,3727,0,0,0,0,0),
  array(0,4395,3888,0,0,0,0,0),
  array(0,4234,3946,0,0,0,0,0),
  array(0,4130,3877,0,0,0,0,0),
  array(0,3808,3658,0,0,0,0,0),
  array(0,3555,2922,0,0,0,0,0),
  array(0,3279,2796,0,0,0,0,0),
  array(0,2830,2876,0,0,0,0,0),
  array(0,2612,3152,0,0,0,0,0),
  array(0,2612,3290,0,0,0,0,0),
  array(0,2853,3670,0,0,0,0,0),
  array(0,3152,3819,0,0,0,0,0),
  array(0,3555,3762,0,0,0,0,0),
  array(0,3831,3647,0,0,0,0,0),
  array(0,4717,2508,0,0,0,0,0),
  array(0,4947,2266,0,0,0,0,0),
  array(0,5338,2232,0,0,0,0,0),
  array(0,5649,2347,0,0,0,0,0),
  array(0,5741,2508,0,0,0,0,0),
  array(0,5649,3003,0,0,0,0,0),
  array(0,5430,3267,0,0,0,0,0),
  array(0,4809,3371,0,0,0,0,0),
  array(0,4740,3060,0,0,0,0,0),
  array(0,4728,2497,0,0,0,0,0),
  array(0,4728,2934,0,0,0,0,0),
  array(0,4832,3382,0,0,0,0,0),
  array(0,5211,4107,0,0,0,0,0),
  array(0,5511,4579,0,0,0,0,0),
  array(0,5511,5154,0,0,0,0,0),
  array(0,5568,4740,0,0,0,0,0),
  array(0,5936,5430,0,0,0,0,0),
  array(0,5557,5637,0,0,0,0,0),
  array(0,5465,5971,0,0,0,0,0),
  array(0,5626,5603,0,0,0,0,0),
  array(0,5948,5407,0,0,0,0,0),
  array(0,6304,5649,0,0,0,0,0),
  array(0,6454,6178,0,0,0,0,0),
  array(0,6224,6810,0,0,0,0,0),
  array(0,6454,6120,0,0,0,0,0),
  array(0,6880,5487,0,0,0,0,0),
  array(0,7064,5039,0,0,0,0,0),
  array(0,6960,4636,0,0,0,0,0),
  array(0,6741,4705,0,0,0,0,0),
  array(0,6695,4774,0,0,0,0,0),
  array(0,6569,4556,0,0,0,0,0),
  array(0,6500,4119,0,0,0,0,0),
  array(0,6845,3750,0,0,0,0,0),
  array(0,7420,3739,0,0,0,0,0),
  array(0,7754,4142,0,0,0,0,0),
  array(0,7811,4935,0,0,0,0,0),
  array(0,7466,5787,0,0,0,0,0),
  array(0,7029,6258,0,0,0,0,0),
  array(0,6224,6810,0,0,0,0,0),
  array(0,5913,7098,0,0,0,0,0),
  array(0,5557,7374,0,0,0,0,0),
  array(0,5223,7340,0,0,0,0,0),
  array(0,5096,7179,0,0,0,0,0),
  array(0,5131,7052,0,0,0,0,0),
  array(0,5304,7006,0,0,0,0,0),
  array(0,5315,6557,0,0,0,0,0),
  array(0,5361,6212,0,0,0,0,0),
  array(0,5465,6017,0,0,0,0,0),
  array(0,4901,7110,0,0,0,0,0),
  array(0,4613,7432,0,0,0,0,0),
  array(0,4280,7386,0,0,0,0,0),
  array(0,4188,7305,0,0,0,0,0),
  array(0,4188,7121,0,0,0,0,0),
  array(0,4337,7098,0,0,0,0,0),
  array(0,4464,6661,0,0,0,0,0),
  array(0,4510,6155,0,0,0,0,0),
  array(0,4648,5879,0,0,0,0,0),
  array(0,4464,6235,0,0,0,0,0),
  array(0,4360,6937,0,0,0,0,0),
  array(0,4153,6856,0,0,0,0,0),
  array(0,3831,6948,0,0,0,0,0),
  array(0,3774,6672,0,0,0,0,0),
  array(0,3843,6258,0,0,0,0,0),
  array(0,3946,6028,0,0,0,0,0),
  array(0,3946,5879,0,0,0,0,0),
  array(0,3877,6270,0,0,0,0,0),
  array(0,3739,6603,0,0,0,0,0),
  array(0,3900,6948,0,0,0,0,0),
  array(0,3946,7052,0,0,0,0,0),
  array(0,3889,7144,0,0,0,0,0),
  array(0,3647,7225,0,0,0,0,0),
  array(0,3474,7190,0,0,0,0,0),
  array(0,3325,7075,0,0,0,0,0),
  array(0,2853,7110,0,0,0,0,0),
  array(0,2669,7052,0,0,0,0,0),
  array(0,2577,6902,0,0,0,0,0),
  array(0,2635,6776,0,0,0,0,0),
  array(0,2750,6684,0,0,0,0,0),
  array(0,2934,6810,0,0,0,0,0),
  array(0,3290,6753,0,0,0,0,0),
  array(0,3302,6580,0,0,0,0,0),
  array(0,2991,6293,0,0,0,0,0),
  array(0,2796,5948,0,0,0,0,0),
  array(0,2853,5591,0,0,0,0,0),
  array(0,3118,5372,0,0,0,0,0),
  array(0,3371,5280,0,0,0,0,0),
  array(0,3233,6074,0,0,0,0,0),
  array(0,3302,6879,0,0,0,0,0),
  array(0,3428,7167,0,0,0,0,0),
  array(0,3244,6718,0,0,0,0,0),
  array(0,3244,6040,0,0,0,0,0),
  array(0,3440,5050,0,0,0,0,0),
  array(0,3543,4625,0,0,0,0,0),
  array(0,3705,4372,0,0,0,0,0),
  array(0,4073,4222,0,0,0,0,0),
  array(0,3647,4395,0,0,0,0,0),
  array(0,3049,4314,0,0,0,0,0),
  array(0,2485,4142,0,0,0,0,0),
  array(0,2290,3981,0,0,0,0,0),
  array(0,2359,3808,0,0,0,0,0),
  array(0,2267,3290,0,0,0,0,0),
  array(0,2060,2658,0,0,0,0,0),
  array(0,1829,2151,0,0,0,0,0),
  array(0,1829,1450,0,0,0,0,0),
  array(0,1956,1116,0,0,0,0,0),
  array(0,1990,967,0,0,0,0,0),
  array(0,1910,748,0,0,0,0,0)
  );
  
  Далее необходимо остальные 6 линий, перпендикулярных плоскости котёнка и друг-другу:
  
  $lineDots = array(
  array(0,0,2000,0,0,0,0,0),
  array(0,0,0,2000,0,0,0,0),
  array(0,0,0,0,2000,0,0,0),
  array(0,0,0,0,0,2000,0,0),
  array(0,0,0,0,0,0,2000,0),
  array(0,0,0,0,0,0,0,2000)
  );
  
  Следующий этап - задача визуализации линий на плоскость, т.к. распространённые существующие средства отображения имеют двумерный формат данных.
  
  Для решения задачи создаём проекционную матрицу:
  $proectionMatrix = array(
  array(0.1,0.1,0.2,0,0,0,0,0,0),
  array(0.4,1,0.3,0,0,0,0,0,0),
  array(0.5,0.6,1,0,0,0,0,0,0),
  array(0,0,0,1,0,0,0,0,0),
  array(0,0,0,0,1,0,0,0,0),
  array(0,0,0,0,0,1,0,0,0),
  array(0,0,0,0,0,0,1,0,0),
  array(0,0,0,0,0,0,0,1,0),
  array(0,0,0,0,0,0,0,0,1));
  
  Значения в матрице для прототипа берём с потолка.
  
  Для улучшения восприятия, будем вращать полученную фигуру по очереди вокруг всех 8-ми осей. Для этого понадобится матрица вращения:
  
  $rotateMatrix = array(
  array(1,0,0,0,0,0,0,0),
  array(0,1,0,0,0,0,0,0),
  array(0,0,1,0,0,0,0,0),
  array(0,0,0,1,0,0,0,0),
  array(0,0,0,0,1,0,0,0),
  array(0,0,0,0,0,1,0,0),
  array(0,0,0,0,0,0,1,0),
  array(0,0,0,0,0,0,0,1),
  );
  
  Которую, в дальнейшем мы будем модифицировать при визуализации фигуры.
  
  Для практической реализации графического вывода используем библиотеку
  include "GIFEncoder.class.php";
  
  Реализуем функции, потребные для выполнения задачи:
  Упрощённое перемножение матриц. Упрощённое, поскольку матрица точки всегда одномерная.
  //перемножить матрицы
  function mulMatrix($a,$b){//$b всегда 1 на n
   $n=count($a);
   $m=count($a[0]);
   $c=array();
   foreach($b as $i => $val){
   $c[$i]=0;
   foreach($a[$i] as $j => $k){
   $c[$i]+=$b[$j]*$k;
   }
   }
   return $c;
  }
  
  //повернуть точку на угол A
  //при этом дополнительно указываем, относительно каких именно осей производится поворот
  function rotateDot($a, $dot, $osx, $osy){
   global $rotateMatrix;
   for($i=0;$i<=$osx;$i++){
   for($j=0;$j<=$osy;$j++){
   $rotateMatrix[$i][$j]=cos($a);
   $rotateMatrix[$i][$j+1]=-sin($a);
   $rotateMatrix[$i+1][$j]=sin($a);
   $rotateMatrix[$i+1][$j+1]=cos($a);
   }
   }
   return mulMatrix($rotateMatrix, $dot);
  }
  
  //отобразить точку на плоскость
  function proectDot($dot){
   global $proectionMatrix;
   $dot[count($dot)]=1;
   $pDot=mulMatrix($proectionMatrix, $dot);
   return array(round($pDot[0]/10 + 150), round($pDot[1]/10+250));
  }
  
  Теперь используя вышеприведённые функции начинаем построение и вывод фигуры:
  
  //перебираем оси
  for($osx=0;$osx<7;$osx++){
  for($osy=0;$osy<7;$osy++){
   //перебираем углы с шагом 10
   for($a=0;$a<36;$a++){
   $alpha=$a*10*3.14 / 180;
   //перебираем линии
   $im = @imagecreate (300, 500) or die ("Cannot Initialize new GD image stream");
   $background_color = imagecolorallocate ($im, 255, 255, 255);
   $red = ImageColorAllocate($im, 255, 0, 0);
  
   //рисуем котёнка
   foreach($catDots as $key=>$dot){
   if($key>0){
   //берём текущую точку и предыдущую
   $d0=rotateDot($alpha, $catDots[$key-1], $osx, $osy);
   $d1=rotateDot($alpha, $catDots[$key], $osx, $osy);
   $d0=proectDot($d0);
   $d1=proectDot($d1);
   //отрисовать
   imageline ($im, $d0[0], $d0[1], $d1[0], $d1[1], $red);
   }
   }
  
   //рисуем прочие линии
   foreach($lineDots as $key=>$line){
   //все линии начинаем в начале координат для наглядности
   $mline=array();
   foreach($line as $x){$mline[]=0;}
   $d0=rotateDot($alpha, $line, $osx, $osy);
   $d1=rotateDot($alpha, $mline, $osx, $osy);
   $d0=proectDot($d0);
   $d1=proectDot($d1);
   //отрисовать
   imageline ($im, $d0[0], $d0[1], $d1[0], $d1[1], $red);
   }
   //сохраняем 1 кадр
   ImageGif($im, "images/anime/".$osx."_".$osy."_".$a.".gif");
   }
  }
  }
  
  if ( $dh = opendir ( "images/anime/" ) ) {
  while ( false !== ( $dat = readdir ( $dh ) ) ) {
  if ( $dat != "." && $dat != ".." ) {
  $frames [ ] = "images/anime/$dat";
  $framed [ ] = 0;
  }
  }
  closedir ( $dh );
  }
  //формируем анимированное изображение
  $gif = new GIFEncoder (
  $frames,
  $framed,
  4000,
  0,
  0, 0, 0,
  "url"
  );
  Header ( 'Content-type:image/gif' );
  
  echo $gif->GetAnimation ( );
  
  Получаем итоговое изображение:
   7 красных линий []
  
  Как видно полученное изображение не отличается визуальным совершенством. Отображение многомерного пространства на двумерное вызывает "слипание" элементов и наш человеческий глаз видит трёхмерную картинку.
  Возможно эту проблему можно решить изменив проекционную матрицу и усовершенствовав алгоритм вращения фигуры.
  
  Так же в данной статье не рассматривались проблемы отображения красных линий зелёным и/или прозрачным цветами.
 Ваша оценка:

Связаться с программистом сайта.

Новые книги авторов СИ, вышедшие из печати:
О.Болдырева "Крадуш. Чужие души" М.Николаев "Вторжение на Землю"

Как попасть в этoт список

Кожевенное мастерство | Сайт "Художники" | Доска об'явлений "Книги"