Добавьте середины в массив и используйте их в следующей итерации
Это звучит очень просто, но я не могу обдумать это:
У меня есть две точки, представляющие координаты X:Y
В первой итерации я хочу добавить среднюю точку двух в массив...
В следующей итерации я хочу добавить среднюю точку первого и второго, а затем среднюю точку между вторым и третьим в массиве... и так далее...
(Я добавляю случайные величины к оси Y, чтобы сделать смещение средней точки) Например,
0:10, 10:10
первая итерация...
0:10, 5:13, 10:10
Вторая итерация...
0:10, 2.5: 12, 5:13, 7.5: 15, 10:10
и т. д.
Вот код, с которым я столкнулся после попытки заставить хоть что-то работать:
<?php
header('Content-type: image/png');
$png_image = imagecreate(1024, 1024);
imagecolorallocate($png_image, 15, 142, 210);
$black = imagecolorallocate($png_image, 0, 0, 0);
imagesetthickness($png_image, 10);
$iterations = 5;
$noise = 10;
$points = array("0:512","1023:512");
for($iteration=0; $iteration < $iterations; $iteration++){
$new_array = array();
ksort($points);
for($i = 0; $i < sizeof($points)-1 ;$i++){
$previous = array("X" => split(":", $points[$i])[0], "Y" => split(":", $points[$i])[1] );
$next = array("X" => split(":", $points[$i+1])[0], "Y" => split(":", $points[$i+1])[1] );
$midpoint = ($previous["X"] + $next["X"])/2;
$midheight = (($previous["Y"] + $next["Y"])/2)+rand(0,$noise);
$npoint="$midpoint:$midheight";
array_push($new_array, $npoint);
}
$points = array_merge($points, $new_array);
}
ksort($points);
for($i=0;$i < sizeof($points)-1;$i++){
$previous = array("X" => split(":", $points[$i])[0], "Y" => split(":", $points[$i])[1] );
$current = array("X" => split(":", $points[$i+1])[0], "Y" => split(":", $points[$i+1])[1] );
// imageline($png_image, (int)$previous["X"], (int)$previous["Y"], (int)$current["X"], (int)$current["Y"], $black);
// imagefilledellipse ( $png_image ,(int)$previous["X"], (int)$previous["Y"] , 8, 8 , $black );
imagestring ($png_image , 4 , (int)$previous["X"], (int)$previous["Y"] , $i , $black);
}
imagepng($png_image);
imagedestroy($png_image);
?>
по некоторым причинам он иногда добавляет точки к одному и тому же x, но с другим значением y.
РЕДАКТИРОВАТЬ: попытаться с функцией
$iterations = 5;
$noise = 10;
$points = array("0:512","1023:512");
$cit = 0;
function divide($pointArray){
global $noise, $cit, $iterations;
$arrayLength = sizeof($pointArray);
$tempArray = $pointArray;
for($i = 0; $i < $arrayLength-1 ;$i++){
$currentPoint = array("X" => split(":", $pointArray[$i])[0], "Y" => split(":", $pointArray[$i])[1] );
$nextPoint = array("X" => split(":", $pointArray[$i+1])[0], "Y" => split(":", $pointArray[$i+1])[1] );
$midpoint = ($currentPoint["X"] + $nextPoint["X"])/2;
$midheight = (($currentPoint["Y"] + $nextPoint["Y"])/2)+rand(0,$noise);
$npoint="$midpoint:$midheight";
array_splice( $tempArray, $i+$i, 0, $npoint );
$cit++;
if($cit < $iterations){
divide($tempArray);
}else{
return $tempArray;
}
2 ответа
Основная проблема заключается в том, что вы рискуете получить ошибки или предупреждения во время выполнения, которые будут выводиться как часть изображения, и это сделает ваше изображение недействительным.
Таким образом, при разработке, вы должны удалить header
заявление, чтобы убедиться, что вы заметили все сообщения об ошибках. И действительно, когда я делаю это с вашим кодом, я получаю:
E_DEPRECATED: тип 8192 - Функция split() устарела
Итак, сначала вам нужно решить это. И когда мы говорим об этом коде, позвольте мне предложить вам не использовать формат "X:Y": хранить координаты таким способом очень неэффективно. Вы распаковываете эту строку в координаты X, Y на каждой итерации, а затем конвертируете ее обратно в строку. Почему бы не сохранить значения массива в числовых координатах X, Y с самого начала?
Вот предлагаемый код:
<?php
$png_image = imagecreate(1024, 1024);
imagecolorallocate($png_image, 15, 142, 210);
$black = imagecolorallocate($png_image, 0, 0, 0);
imagesetthickness($png_image, 10);
$iterations = 5;
$noise = 10;
// Don't use string format "X:Y" for doing manipulations.
// If you still need that format afterwards, do that conversion later.
$points = array(
array(
"X" => 0,
"Y" => 512
),
array(
"X" => 1023,
"Y" => 512
)
);
for($iteration=0; $iteration < $iterations; $iteration++){
$new_array = array($points[0]);
for($i = 0; $i < sizeof($points)-1; $i++){
$previous = $points[$i];
$next = $points[$i+1];
$midpoint = array(
"X" => ($previous["X"] + $next["X"])/2,
"Y" => ($previous["Y"] + $next["Y"])/2 + rand(0,$noise)
);
array_push($new_array, $midpoint);
array_push($new_array, $next);
}
$points = $new_array;
}
for($i=0; $i < sizeof($points)-1; $i++){
$previous = $points[$i];
$next = $points[$i+1];
imagestring ($png_image , 4 , (int)$previous["X"], (int)$previous["Y"] , $i , $black);
}
// Put header statement in comments for as long as you have errors:
header('Content-type: image/png');
imagepng($png_image);
imagedestroy($png_image);
?>
Я не знаю много с точки зрения php, но позвольте мне попытаться помочь с общей логикой. Пример кода в javascript, но я могу попытаться объяснить.
var midPointDisplace = function(pt1, pt2, depth, accum){
// Create the mid point.
var pt3 = [(pt1[0] + pt2[0]) / 2 + (Math.random()-0.5), (pt1[1] + pt2[1]) / 2 + (Math.random()-0.5)];
if (depth == 0){
// if the recursion depth reaches 0. Push the midpoint in to the accumulator array.
accum.push(pt3);
}else{
// Otherwise, recurse down.
midPointDisplace(pt1, pt3, depth - 1, accum); // Ask the next depth in the recursion to generate the points between pt1 (previous point) and pt3 (current mid point).
accum.push(pt3); // Push/append the current midpoint
midPointDisplace(pt3, pt2, depth - 1, accum); // Ask the next depth in the recursion to generate the points between pt3 and pt2 (the next point).
}
}
Выше приведена основная "рабочая лошадка" логики, по сути, перед ней стоит задача создать все средние точки между pt1 и pt2 и рекурсивную при необходимости. Вышеуказанный цикл можно инициализировать, как показано ниже.
var initPoint = function(pt1, pt2, depth, accum){
accum.push(pt1); // Push the first point.
midPointDisplace(pt1, pt2 ,depth, accum); // Generate all the mid points.
accum.push(pt2); // Push the last point.
}
Свойство "аккумулировать" должно быть передано как ссылка, чтобы каждый этап рекурсии "наращивал". После возврата в функцию будет записано то, что вы хотите.
Свойство глубины, по сути, указывает, сколько раз вы хотите выполнить генерацию средней точки.