Skip to content

Commit 8ac3905

Browse files
committed
Init
0 parents  commit 8ac3905

File tree

5 files changed

+417
-0
lines changed

5 files changed

+417
-0
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Mandelbrot set simple PHP Generator
2+
===================================
3+
4+
Simple Generator for create image of Mandelbrot set as base64 by full-configuration request.
5+
6+
This package was inspired by Pavol Hejný.
7+
8+
Install
9+
-------
10+
11+
By Composer:
12+
13+
```shell
14+
mathematicator-core/mandelbrot-set
15+
```
16+
17+
Use
18+
---
19+
20+
Inject `MandelbrotSet` service to your application, create new Request and process by `loadImage()` method.

composer.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "mathematicator-core/mandelbrot-set",
3+
"description": "Mandelbrot set simple PHP Generator.",
4+
"homepage": "https://github.com/mathematicator-core/mandelbrot-set",
5+
"authors": [
6+
{
7+
"name": "Jan Barášek",
8+
"homepage": "http://baraja.cz"
9+
},
10+
{
11+
"name": "Pavol Hejný",
12+
"homepage": "https://www.pavolhejny.com"
13+
}
14+
],
15+
"require": {
16+
"php": ">=7.1",
17+
"nette/utils": "^3.0"
18+
},
19+
"autoload": {
20+
"classmap": [
21+
"src/"
22+
]
23+
},
24+
"minimum-stability": "stable"
25+
}

config.neon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
services:
2+
- Mathematicator\MandelbrotSet\MandelbrotSet(%tempDir%/mandelbrot-set)

src/MandelbrotSet.php

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Mathematicator\MandelbrotSet;
6+
7+
/**
8+
* Calculate and render Mandelbrot set as image to file.
9+
* Implementation is inspired by Pavol Hejny, https://www.pavolhejny.com/.
10+
*/
11+
class MandelbrotSet
12+
{
13+
14+
/**
15+
* @var string
16+
*/
17+
private $tempDir;
18+
19+
/**
20+
* @param string $tempDir
21+
* @throws \Exception
22+
*/
23+
public function __construct(string $tempDir)
24+
{
25+
ini_set('max_execution_time', '100000');
26+
27+
if (!is_dir($tempDir) && !@mkdir($tempDir, 0777, true) && !is_dir($tempDir)) { // @ - dir may already exist
28+
throw new \Exception(
29+
'Unable to create directory "' . $tempDir . '". '
30+
. preg_replace('#^\w+\(.*?\): #', '', error_get_last()['message'])
31+
);
32+
}
33+
34+
$this->tempDir = $tempDir;
35+
}
36+
37+
/**
38+
* Load image from temp by Request and return as base64 image.
39+
*
40+
* @param MandelbrotSetRequest $request
41+
* @return string
42+
*/
43+
public function loadImage(MandelbrotSetRequest $request): string
44+
{
45+
if (is_file($path = $this->tempDir . '/' . $request->getFileName()) === false) {
46+
$this->generate($request);
47+
}
48+
49+
return 'data:' . mime_content_type($path) . ';base64,' . base64_encode(file_get_contents($path));
50+
}
51+
52+
/**
53+
* Process image by request and save to temp file.
54+
*
55+
* @param MandelbrotSetRequest $request
56+
*/
57+
public function generate(MandelbrotSetRequest $request): void
58+
{
59+
[$w, $h, $itt, $min_x, $max_x, $min_y, $max_y, $d1, $d2] = $request->getParams();
60+
61+
$dim_x = $w;
62+
$dim_y = $h;
63+
$im = imagecreatetruecolor((int) $dim_x, (int) $dim_y);
64+
imagealphablending($im, false);
65+
imagesavealpha($im, true);
66+
67+
$blackColor = imagecolorallocate($im, 0, 0, 0);
68+
$alpha_color = imagecolorallocatealpha($im, 0, 0, 0, 127);
69+
imagefill($im, 0, 0, $alpha_color);
70+
71+
for ($y = 0; $y <= $dim_y; $y++) { // Procházení a vyhodnocení každého bodu
72+
for ($x = 0; $x <= $dim_x; $x++) { // Zjištění souřadnic bodu, který se přičte v každé iteraci
73+
$c1 = $min_x + ($max_x - $min_x) / $dim_x * $x;
74+
$c2 = $min_y + ($max_y - $min_y) / $dim_y * $y;
75+
$z1 = 0; // aktuální číslo
76+
$z2 = 0;
77+
78+
for ($i = 0; $i < $itt; $i++) { // Main iterator
79+
// Zjištění vzdálenosti od 0+0i
80+
$distance = sqrt($z1 * $z1 + $z2 * $z2);
81+
82+
if ((int) $distance !== 0) {
83+
$angle = acos($z1 / $distance);
84+
} else {
85+
$angle = 0;
86+
}
87+
88+
if ($z2 < 0) { // Úhel
89+
$angle = (2 * M_PI) - $angle;
90+
}
91+
92+
$angle *= $d1; // Vynásobení úhlu
93+
$distance = $distance ** $d2; // Mocnění vzdálenosti
94+
// Výpočet nového x,y
95+
$z1 = cos($angle) * $distance;
96+
$z2 = sin($angle) * $distance;
97+
// Přičtení souřadnic bodu
98+
$z1 += $c1;
99+
$z2 += $c2;
100+
101+
// Pokud je bod ve vzdálenosti 2 nebo větší, bod v množině nebude a iterování lze ukončit
102+
if ($z1 * $z1 + $z2 * $z2 >= 4) {
103+
break;
104+
}
105+
}
106+
107+
// Pokud v každé iteraci držel nový bod ve vzdálenosti 2 nebo méně, je původní bod vyplněn.
108+
if ($i >= $itt) {
109+
imagesetpixel($im, (int) round($x), (int) round($y), $blackColor);
110+
}
111+
}
112+
}
113+
114+
// Save to file
115+
imagesavealpha($im, true);
116+
imagepng($im, $path = $this->tempDir . '/' . $request->getFileName());
117+
imagedestroy($im);
118+
}
119+
120+
/**
121+
* @param int $width
122+
* @param int $height
123+
*/
124+
public function renderAll(int $width = 300, int $height = 300): void
125+
{
126+
$minX = -2; // Levý okraj
127+
$maxX = 1; // Pravý okraj
128+
$minY = ($height * ($maxX - $minX) / $width) / -2;// Horní okraj
129+
$maxY = ($height * ($maxX - $minX) / $width) / 2;// Dolní okraj
130+
131+
// čísla, kterými se bude násobit uhel
132+
$ax = [];
133+
for ($x = -7; $x <= 3; $x++) {
134+
$ax[] = $x;
135+
}
136+
sort($ax);
137+
138+
$ay = []; // čísla, kterými se bude mocnit vzdálenost
139+
for ($y = 0; $y <= 4; $y++) {
140+
$ay[] = $y;
141+
}
142+
sort($ay);
143+
144+
array_unshift($ax, false);
145+
array_unshift($ay, false);
146+
147+
echo '<table>';
148+
foreach ($ay as $d2) {
149+
echo '<tr>';
150+
foreach ($ax as $d1) {
151+
if ($d1 !== false && $d2 !== false) {
152+
$request = new MandelbrotSetRequest($d1, $d2, $width, $height, 18, $minX, $maxX, $minY, $maxY);
153+
154+
if ($d1 * $d2 % 2) {
155+
$bgColor = 'eeeeee';
156+
} elseif ($d1 % 2) {
157+
$bgColor = 'f5f5f5';
158+
} elseif ($d2 % 2) {
159+
$bgColor = 'f5f5f5';
160+
} else {
161+
$bgColor = 'fbfbfb';
162+
}
163+
164+
echo '<td bgcolor="' . $bgColor . '"><img src="' . $this->loadImage($request) . '" border="0"></td>';
165+
} elseif ($d1 === false && $d2 !== false) { // Zobrazení popisku osy
166+
echo('<td valign="middle">');
167+
168+
if ((int) round($d2) === (int) $d2) {
169+
echo '<h2>^' . $d2 . '&nbsp;</h2>';
170+
} else {
171+
echo '^' . $d2 . '&nbsp;';
172+
}
173+
174+
echo '</td>';
175+
} elseif ($d2 === false && $d1 !== false) { // Zobrazení popisku osy
176+
echo '<td align="center">';
177+
178+
if ((int) round($d1) === (int) $d1) {
179+
echo '<h2>*' . $d1 . '</h2>';
180+
} else {
181+
echo '*' . $d1 . '';
182+
}
183+
184+
echo '</td>';
185+
} else {
186+
echo '<td>&nbsp;</td>';
187+
}
188+
}
189+
echo '</tr>';
190+
}
191+
echo '</table>';
192+
}
193+
194+
}

0 commit comments

Comments
 (0)