Grafy goniometrických funkcí

UkázkaPřed nedávnem jsme ve škole dělali goniometrické funkce a vše co k nim patří. Proto jsem si udělal pomůcku díky, které jsme měl vždy úkol hotový. Chvíli jsem na tom pracoval – fungují tam i posuvy, ale boužel jsem neudělal dynamické měřítko. A to z jednoho prostého důvodu: nenapadlo mě, že by mohla nastat taková situace, že by se graf mohl posouvat po ose x do mínusu(do prava). Takže boužel dokážet zobrazovat graf jen od –360° do + 360°. Většině lidem, kteří jsou ve 2. ročníku střední školy se toto může hodit.

Skript umí posuvy po osách, kromě výše zmíněné chyby, umí vykreslit funkce: sinus, kosinus, tangens, kotangens, sekans, kosekans. Zvýrazněné tučně umí zobrazit dobře ty ostatní trochu blbnou. Opravit by to šlo, ale nechce se mi to dělat :-). Celý skript je psaný v PHP jako třída. Dávám ho sem jako „opensource“. Tak snad se někomu bude hodit.

Kód ukazky

<?php
  include "./trigonometric.class.php";
  $trigonometricFunction = new trigonometricFunction("Grafy goniometrických funkcí");
  $trigonometricFunction->addColor(array(82, 208, 235));
  $trigonometricFunction->addColor(array(128, 255, 20));
  $trigonometricFunction->addColor(array(128, 55, 100));
  $trigonometricFunction->addColor(array(175, 54, 54));
  $trigonometricFunction->addColor(array(10, 111, 150));
  $trigonometricFunction->addColor(array(195, 14, 214));
  $trigonometricFunction->addFunction("f:y=cos(2*x)-1");
  $trigonometricFunction->addFunction("f:y=sin(2*x)+1");
  $trigonometricFunction->addFunction("f:y=cos(x+360)+1");
  $trigonometricFunction->addFunction("f:y=sin(x+360)-1");
?>

Kód třídy

<?php
/*
  * Martin Bumba 2007
  *  Grafy goniometrických funkcí - opensource
*/
function tg($x) {
  return tan($x);
}
function cotg($x) {
  return @(cos($x)/sin($x));
}
function sec($x) {
  return (1/cos($x));
}
function cosec($x) {
  return @(1/sin($x));
}
class trigonometricFunction {
  var $width = 800;
  var $height = 640;
  var $name = "Graf goniometrické funkce";
  var $fontPath = "/home/www/evil666.net/subdomains/www/examples/trigonometric/";
  var $fontFile = "tahoma.ttf";
  var $antialias = 1; //1 - antialias is turned off ; 2 -> 10 - antialias step (turned on)
  var $image;
  var $border = 14;
  var $backgroundColor = array(255, 255, 255);
  var $titleColor = array(110, 110, 110);
  var $borderColor = array(210, 210, 210);
  var $borderTop = 12;
  var $functions = array();
  var $functionColors; /*array(
                                array(82, 208, 235),
                                array(150, 108, 235)
                              ); */
  function __construct($name = false, $width = false, $height = false) {
    if(!empty($name)) {
      $this->name = $this->encodeString(htmlspecialchars($name));
    }
    if(!empty($width) AND is_numeric($width)) {
      $this->width = round($width);
    }

    if(!empty($height) AND is_numeric($height)) {
      $this->height = round($height);
    }
  }
  private function encodeString($input) {
    $UTFtable = array(  "Č"=>268, "č"=>269,
                        "Ď"=>270, "ď"=>271,
                        "Ě"=>282, "ě"=>283,
                        "Ň"=>327, "ň"=>328,
                        "Ř"=>344, "ř"=>345,
                        "Š"=>352, "š"=>353,
                        "Ť"=>356, "ť"=>357,
                        "Ů"=>366, "ů"=>367,
                        "Ž"=>381, "ž"=>382);
    $output = "";
    for($i=0; $i < strlen($input); $i++) {
      if ($UTFtable[$vstup_str[$i]]) {
        $output .= "&#" . $UTFtable[$input[$i]] . ";";
      }
      else {
        $output .= $input[$i];
      }
    }
    return $output;
  }
  public function changeFont($newFontFile = false) {
    if(preg_match('/.*?\.ttf/sim', $newFontFile) AND file_exists($this->fontPath . str_replace(array("/", "\\"), "", $newFontFile))) {
      $this->fontFile = $newFontFile;
    }
  }
  private function drawAxis($color, $pointColor, $fontColor, $labels) {
    $jumper = (($this->width - (2 * $this->border))/2)/360;
    #Axis X
    $x_x1 = $this->border;
    $x_x2 = $this->width - $this->border;
    $x_y = ($this->height + $this->borderTop) / 2 ;
    imageLine($this->image, $x_x1, $x_y, $x_x2, $x_y, $color);
    $xWidth = $this->width - 2 * $this->border;
    $xLabel =  -round(round($xWidth / 20) / 2);
    for($i = 0; $i <= 720; $i = $i + 5) {
      $pointHeight = 2;
      if($i % 30 == 0 ) {
        $label = -360 + $i;  //"π"
        if(strlen($label) == 3) {
          $label = " " . $label;
        }
        elseif(strlen($label) == 2 AND $label>0) {
          $label = "  " . $label;
        }
        $pointHeight = 5;
        imageTtfText($this->image, 8, 0, $this->border + $i * $jumper - 14, $x_y + 20, $fontColor, $this->fontPath . $this->fontFile, $label. "°");
      }
      imageLine($this->image, $this->border + $i * $jumper, $x_y - $pointHeight, $this->border + $i * $jumper, $x_y + $pointHeight, $color);
    }
    #Axis Y
    $y_x = $this->width/2;
    $y_y1 = $this->border + $this->borderTop;
    $y_y2 = $this->height - $this->border;
    $this->axisYtopY = $y_y1;
    $this->axisYbottomY = $y_y2;
    imageLine($this->image, $y_x, $y_y1, $y_x, $y_y2, $color);
    $yHeight = $this->height - 2 * $this->border - $this->borderTop;
    $yLabel =  round(round($yHeight / 100) / 2);
    for($i = 0; $i <= $yHeight; $i++) {
      $pointWidth = 2;
      if($i % 50 == 0) {
        $labelHelper = "";
        $pointWidth = 5;
        if(strlen($yLabel) == 1) {
          $labelHelper = "  ";
        }
        elseif(strlen($yLabel) == 2) {
          $labelHelper = " ";
        }
        if($yLabel != 0) imageTtfText($this->image, 8, 0, $y_x - 25, $this->border + $this->borderTop + $i + 4, $fontColor, $this->fontPath . $this->fontFile, $labelHelper . $yLabel);
        $yLabel -= 0.5;
      }
      if($i % 5 == 0 ) {

        imageLine($this->image, $y_x - $pointWidth, $this->border + $this->borderTop + $i, $y_x + $pointWidth, $this->border + $this->borderTop + $i, $color);
      }
    }
  }
  public function addFunction($function = false) {
    $function = strtolower(str_replace(" ", "", htmlspecialchars($function)));
    if(preg_match('/f:y=(.*?)\((.*?)\)(.*)/sim', $function, $matches)) {
      if($matches[1]=="sin" OR $matches[1]=="cos" OR $matches[1]=="tg" OR $matches[1]=="cotg" OR $matches[1]=="sec" OR $matches[1]=="cosec") {
        if(!empty($matches[2])) {

          $this->functions[] = array("fullFunction" => $matches[0], "function" => $matches[1], "argument" => htmlspecialchars($matches[2]), "argument_2" => htmlspecialchars($matches[3]));
        }
      }
    }
  }
  private function drawFunctions($colors) {
    $y = ($this->height + $this->borderTop) / 2;
    $jumper = (($this->width - (2 * $this->border))/2)/360;
    $f = 0;
    $feed = 0;
    foreach($this->functions AS $function) {
      $x = $this->width / 2;
      if($feed_e = explode('+', $function["argument"])) {
        $feed = $feed_e[1];
      }
      if($feed_e = explode('-', $function["argument"])) {
        $feed -= $feed_e[1];
      }
      if(!empty($feed)) {
        $x += $feed * (-1 ) * $jumper;
        $function["argument"] = $feed_e[0];
      }
      for($i=0;$i<=360;$i++) {
        $now_argument = str_replace("x", $i, $function["argument"]);
        eval("\$now_argument = ".$now_argument.";");
        $y_value = $function["function"](deg2rad($now_argument));
        if($y_value OR $y_value==0) {
          if(!empty($function["argument_2"])) {
            eval("\$y_value = ".$y_value." ".$function["argument_2"].";");
          }
          $y_value = 100 * round(-1 * $y_value ,2);
          $rew = 1;
          if($now_argument<0) {
            $rew = -1;
          }
          if($i!=0) {

            imageSetThickness($this->image, 1);
            imageLine($this->image, $x + $i * $jumper -1, $y + $back_y_value, $x + $i * $jumper, $y + $y_value, $colors[$f]);
            imageSetThickness($this->image, 1);
          }
          $back_y_value = $y_value;
        }
      }
      $f++;
      if(count($colors) == $f) $f = 0;
    }
  }
  private function getColors($colors) {
    $output_colors = array();
    foreach($colors AS $color) {
      $output_colors[] = imageColorAllocate($this->image, $color[0], $color[1], $color[2]);
    }
    return $output_colors;
  }
  public function addColor($color) {
    if(!empty($color)) {
      $this->functionColors[] = array($color[0], $color[1], $color[2]);
    }
    return true;
  }
  private function labelColor($x, $y, $size, $color, $border_color) {
    $points = Array(
                    $x, $y,
                    $x + $size, $y,
                    $x + $size, $y + $size,
                    $x, $y + $size
                   );
    $border_size = 1;
    ImageLine($this->image, $x - $border_size, $y - $border_size, $x + $size + $border_size, $y - $border_size, $border_color);
    ImageLine($this->image, $x - $border_size, $y, $x - $border_size , $y + $size + $border_size, $border_color);
    ImageLine($this->image, $x, $y + $size + $border_size, $x + $size + $border_size , $y + $size + $border_size, $border_color);
    ImageLine($this->image, $x + $size + $border_size, $y + $size + $border_size, $x + $size + $border_size, $y, $border_color);
    ImageFilledPolygon($this->image, $points, 4, $color);
  }
  private function drawLegend($colors) {
    $stepLegend = 15;
    $width = 150;
    $xLegend = $this->width - $width - 1;
    $yLegend = $this->height - $stepLegend * count($this->functions) - 1;
    $points = Array(
                    $xLegend, $yLegend,
                    $xLegend, $yLegend + $stepLegend * count($this->functions),
                    $xLegend + $width, $yLegend + $stepLegend * count($this->functions),
                    $xLegend + $width, $yLegend
                   );
    ImageFilledPolygon($this->image, $points, 4, imageColorAllocate($this->image, $this->backgroundColor[0], $this->backgroundColor[1], $this->backgroundColor[2]));
    ImagePolygon($this->image, $points, 4, imageColorAllocate($this->image, $this->borderColor[0], $this->borderColor[1], $this->borderColor[2]));
    $f = 0;
    $xLegend += 5;
    $yLegend += 5;
    foreach($this->functions AS $function) {
      $this->labelColor($xLegend, $yLegend, 6, $colors[$f], imageColorAllocate($this->image, $this->borderColor[0], $this->borderColor[1], $this->borderColor[2]));
      ImageTtfText($this->image, 8, 0, $xLegend+10, $yLegend+7, imageColorAllocate($this->image, $this->titleColor[0], $this->titleColor[1], $this->titleColor[2]), $this->fontPath . $this->fontFile, $this->encodeString($function["fullFunction"]));
      $yLegend += $stepLegend;
      $f++;
      if(count($colors) == $f) $f = 0;
    }
  }
  function __destruct() {
    header("Content-type: image/png");
    $this->width = $this->width * $this->antialias;
    $this->height = $this->height * $this->antialias;
    $this->image = ImageCreateTrueColor($this->width, $this->height);
    $white = imageColorAllocate($this->image, 255, 255, 255);
    $black = imageColorAllocate($this->image, 0, 0, 0);
    $gray = imageColorAllocate($this->image, 120, 120, 120);
    imageFill($this->image, 0, 0, imageColorAllocate($this->image, $this->backgroundColor[0], $this->backgroundColor[1], $this->backgroundColor[2]));
    $this->drawAxis($black, $black, $gray, false);
    $this->drawFunctions($this->getColors($this->functionColors));
    $this->drawLegend($this->getColors($this->functionColors));
    $titleTtfBox = ImageTtfbbox (14, 0, $this->fontPath . $this->fontFile, $this->encodeString($this->name));
    $titleWidth = $titleTtfBox[2] - $titleTtfBox[0];
    $xTitle = round((($this->width)-$titleWidth)/2);
    ImageTtfText($this->image, 14, 0, $xTitle, 16, imageColorAllocate($this->image, $this->titleColor[0], $this->titleColor[1], $this->titleColor[2]), $this->fontPath . $this->fontFile, $this->encodeString($this->name));
    imagePNG($this->image);
    imageDestroy($this->image);
  }
}
?>

před 1519 dny, 09. 12. 2007Programování

Komentáře

[1] Cynebeald

Takova technicka poznamka – nestaci ze nekam napises ze je neco „opensource“ protoze ta definice je tak siroka ze v podstate vubec nic neznamena (podobne jako pouhe oznaceni „freeware“ nic neznamena).

Takze bych ti doporucil projit si nektery konkretni opensource licence a nejakou vybrat (pro jednoduchost treba licenci typu creative commons) protoze do ty doby si s tim muze kazdej delat co chce.

A asi by to taky chtelo si projit pravidla ceskyho pravopisu, z ty prvni vety by si nekdo moh myslet ze jsi holka ;-)

Zasláno před 1518 dny | Odpovědět
Na komentář reagoval [2] Martin

[2] Martin Favicon

[1] Cynebeald: Ano máš pravdu asi bude vhodnější dát tomu licenci GPL. Jo za chyby se omlouvám, čeština nikdy nebyla má silná stránka :-(. Ta první věta už by měla byt ok :-).

Zasláno před 1518 dny | Odpovědět
Na komentář reagoval [3] Cynebeald

[3] Cynebeald

[2] Martin: No, GPL licence je pro mnoho pripadu pouziti zase prilis restriktivni. Napriklad to znamena, ze tu tridu nemuze nikdo pouzit v programu ktery neni sam o sobe GPL, coz muze (ale nemusi) byt to co chces. Mimo jine to znamena, ze ten kod neni mozny pouzit ani v jinym opensource programu pokud ma treba BSD nebo Apache licenci.

Neni opensource jako opensource ;-)

Zasláno před 1518 dny | Odpovědět
Na komentář reagoval [4] Martin

[4] Martin Favicon

[3] Cynebeald: :D Tak mi řekni co mám zvolit jako licenci?

Zasláno před 1518 dny | Odpovědět

Zanechat komentář




Antispam