diff --git a/README.md b/README.md new file mode 100644 index 0000000..3016950 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +Mandelbrot set simple PHP Generator +=================================== + +Simple Generator for create image of Mandelbrot set as base64 by full-configuration request. + +This package was inspired by Pavol Hejný. + +Install +------- + +By Composer: + +```shell +mathematicator-core/mandelbrot-set +``` + +Use +--- + +Inject `MandelbrotSet` service to your application, create new Request and process by `loadImage()` method. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d7bab8d --- /dev/null +++ b/composer.json @@ -0,0 +1,25 @@ +{ + "name": "mathematicator-core/mandelbrot-set", + "description": "Mandelbrot set simple PHP Generator.", + "homepage": "https://github.com/mathematicator-core/mandelbrot-set", + "authors": [ + { + "name": "Jan Barášek", + "homepage": "http://baraja.cz" + }, + { + "name": "Pavol Hejný", + "homepage": "https://www.pavolhejny.com" + } + ], + "require": { + "php": ">=7.1", + "nette/utils": "^3.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "minimum-stability": "stable" +} \ No newline at end of file diff --git a/config.neon b/config.neon new file mode 100644 index 0000000..2ff269e --- /dev/null +++ b/config.neon @@ -0,0 +1,2 @@ +services: + - Mathematicator\MandelbrotSet\MandelbrotSet(%tempDir%/mandelbrot-set) \ No newline at end of file diff --git a/src/MandelbrotSet.php b/src/MandelbrotSet.php new file mode 100644 index 0000000..a055551 --- /dev/null +++ b/src/MandelbrotSet.php @@ -0,0 +1,194 @@ +tempDir = $tempDir; + } + + /** + * Load image from temp by Request and return as base64 image. + * + * @param MandelbrotSetRequest $request + * @return string + */ + public function loadImage(MandelbrotSetRequest $request): string + { + if (is_file($path = $this->tempDir . '/' . $request->getFileName()) === false) { + $this->generate($request); + } + + return 'data:' . mime_content_type($path) . ';base64,' . base64_encode(file_get_contents($path)); + } + + /** + * Process image by request and save to temp file. + * + * @param MandelbrotSetRequest $request + */ + public function generate(MandelbrotSetRequest $request): void + { + [$w, $h, $itt, $min_x, $max_x, $min_y, $max_y, $d1, $d2] = $request->getParams(); + + $dim_x = $w; + $dim_y = $h; + $im = imagecreatetruecolor((int) $dim_x, (int) $dim_y); + imagealphablending($im, false); + imagesavealpha($im, true); + + $blackColor = imagecolorallocate($im, 0, 0, 0); + $alpha_color = imagecolorallocatealpha($im, 0, 0, 0, 127); + imagefill($im, 0, 0, $alpha_color); + + for ($y = 0; $y <= $dim_y; $y++) { // Procházení a vyhodnocení každého bodu + for ($x = 0; $x <= $dim_x; $x++) { // Zjištění souřadnic bodu, který se přičte v každé iteraci + $c1 = $min_x + ($max_x - $min_x) / $dim_x * $x; + $c2 = $min_y + ($max_y - $min_y) / $dim_y * $y; + $z1 = 0; // aktuální číslo + $z2 = 0; + + for ($i = 0; $i < $itt; $i++) { // Main iterator + // Zjištění vzdálenosti od 0+0i + $distance = sqrt($z1 * $z1 + $z2 * $z2); + + if ((int) $distance !== 0) { + $angle = acos($z1 / $distance); + } else { + $angle = 0; + } + + if ($z2 < 0) { // Úhel + $angle = (2 * M_PI) - $angle; + } + + $angle *= $d1; // Vynásobení úhlu + $distance = $distance ** $d2; // Mocnění vzdálenosti + // Výpočet nového x,y + $z1 = cos($angle) * $distance; + $z2 = sin($angle) * $distance; + // Přičtení souřadnic bodu + $z1 += $c1; + $z2 += $c2; + + // Pokud je bod ve vzdálenosti 2 nebo větší, bod v množině nebude a iterování lze ukončit + if ($z1 * $z1 + $z2 * $z2 >= 4) { + break; + } + } + + // Pokud v každé iteraci držel nový bod ve vzdálenosti 2 nebo méně, je původní bod vyplněn. + if ($i >= $itt) { + imagesetpixel($im, (int) round($x), (int) round($y), $blackColor); + } + } + } + + // Save to file + imagesavealpha($im, true); + imagepng($im, $path = $this->tempDir . '/' . $request->getFileName()); + imagedestroy($im); + } + + /** + * @param int $width + * @param int $height + */ + public function renderAll(int $width = 300, int $height = 300): void + { + $minX = -2; // Levý okraj + $maxX = 1; // Pravý okraj + $minY = ($height * ($maxX - $minX) / $width) / -2;// Horní okraj + $maxY = ($height * ($maxX - $minX) / $width) / 2;// Dolní okraj + + // čísla, kterými se bude násobit uhel + $ax = []; + for ($x = -7; $x <= 3; $x++) { + $ax[] = $x; + } + sort($ax); + + $ay = []; // čísla, kterými se bude mocnit vzdálenost + for ($y = 0; $y <= 4; $y++) { + $ay[] = $y; + } + sort($ay); + + array_unshift($ax, false); + array_unshift($ay, false); + + echo '
'; + } elseif ($d1 === false && $d2 !== false) { // Zobrazení popisku osy + echo(' | ');
+
+ if ((int) round($d2) === (int) $d2) {
+ echo '^' . $d2 . ''; + } else { + echo '^' . $d2 . ' '; + } + + echo ' | ';
+ } elseif ($d2 === false && $d1 !== false) { // Zobrazení popisku osy
+ echo '';
+
+ if ((int) round($d1) === (int) $d1) {
+ echo '*' . $d1 . ''; + } else { + echo '*' . $d1 . ''; + } + + echo ' | ';
+ } else {
+ echo ''; + } + } + echo ' |