Skip to content

Instantly share code, notes, and snippets.

@rzfarrell
Created July 13, 2017 12:44
Show Gist options
  • Save rzfarrell/3a9e5046dcfd6bd2d2f4bfa1a34b21ef to your computer and use it in GitHub Desktop.
Save rzfarrell/3a9e5046dcfd6bd2d2f4bfa1a34b21ef to your computer and use it in GitHub Desktop.
Translate 3D object onto 2D space
<?php
function RotatePoint($sin,$cos,$x,$y) {
return array($x*$cos - $y*$sin, $y*$cos + $x*$sin);
}
function draw_boxes($image_name, $image_size, $boxes)
{
$image = imagecreatetruecolor($image_size, $image_size);
imageantialias($image, true);
$white = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image, 0, 0, $image_size, $image_size, $white);
$brown = imagecolorallocate($image, 120, 53, 31);
$green = imagecolorallocate($image, 23, 255, 65);
$blue = imagecolorallocate($image, 31, 23, 255);
$orange = imagecolorallocate($image, 255, 185, 23);
$camx = 0;
$camy = 0;
$camz = 0;
$yaw = deg2rad(-25);
$pitch = deg2rad(55);
$sy = sin(-$yaw); $cy = cos(-$yaw); $sp = sin(-$pitch); $cp = cos(-$pitch);
$scale = 1;
$x_adjustment = ($image_size-20)/2;
$z_adjustment = ($image_size-20)/2;
$boxes[0]['color'] = $brown;
$boxes[] = $boxes[0];
$temp_boxes = array();
foreach ($boxes as $box_num => $box)
{
$temp_boxes[] = $box;
if (isset($box['fill']) && $box['fill'] === true)
{
$box['fill'] = false;
$box['color'] = imagecolorallocate($image, 70, 70, 70);
$temp_boxes[] = $box;
}
}
$boxes = $temp_boxes;
foreach ($boxes as $box_num => $box)
{
$width = $box['width'];
$length = $box['length'];
$height = $box['height'];
$start_x = $box['start'][0];
$start_y = $box['start'][1];
$start_z = $box['start'][2];
$faces = array();
// Draw 6 faces
for ($i = 0; $i < 6; $i++)
{
switch ($i)
{
case 0:
$face = array(
array($start_x, $start_y, $start_z),
array($start_x+$width, $start_y, $start_z),
array($start_x+$width, $start_y, $start_z+$height),
array($start_x, $start_y, $start_z+$height)
);
break;
case 1:
$face = array(
array($start_x, $start_y+$length, $start_z),
array($start_x+$width, $start_y+$length, $start_z),
array($start_x+$width, $start_y+$length, $start_z+$height),
array($start_x, $start_y+$length, $start_z+$height)
);
break;
case 2:
$face = array(
array($start_x, $start_y, $start_z),
array($start_x, $start_y+$length, $start_z),
array($start_x, $start_y+$length, $start_z+$height),
array($start_x, $start_y, $start_z+$height)
);
break;
case 3:
$face = array(
array($start_x+$width, $start_y, $start_z),
array($start_x+$width, $start_y+$length, $start_z),
array($start_x+$width, $start_y+$length, $start_z+$height),
array($start_x+$width, $start_y, $start_z+$height)
);
break;
case 4:
$face = array(
array($start_x, $start_y, $start_z+$height),
array($start_x+$width, $start_y, $start_z+$height),
array($start_x+$width, $start_y+$length, $start_z+$height),
array($start_x, $start_y+$length, $start_z+$height)
);
break;
case 5:
$face = array(
array($start_x, $start_y, $start_z),
array($start_x+$width, $start_y, $start_z),
array($start_x+$width, $start_y+$length, $start_z),
array($start_x, $start_y+$length, $start_z)
);
break;
}
foreach ($face as $key => $point)
{
$x = $point[0] - $camx;
$y = $point[1] - $camy;
$z = $point[2] - $camz;
$rot = RotatePoint($sy,$cy,$x,$y);
$face[$key]['x'] = $rot[0];
$face[$key]['y'] = $rot[1];
$rot = RotatePoint($sp,$cp,$z,$face[$key]['y']);
$face[$key]['z'] = $rot[0];
$face[$key]['y'] = $rot[1];
}
$faces[] = $face;
}
// BOX 0 SHOULD BE THE LARGEST SO WE CAN FIND THE BOUNDRIES AND SET THE SCALE AND ADJUSTMENTS TO CENTER THE IMAGE
if ($box_num == 0)
{
$min_x = 100000;
$max_x = -100000;
$min_z = 100000;
$max_z = -100000;
foreach ($faces as $face)
{
foreach ($face as $point)
{
if ($point['x'] < $min_x) $min_x = $point['x'];
if ($point['x'] > $max_x) $max_x = $point['x'];
if ($point['z'] < $min_z) $min_z = $point['z'];
if ($point['z'] > $max_z) $max_z = $point['z'];
}
}
$diff_x = $max_x - $min_x;
$diff_z = $max_z - $min_z;
$scale = ($image_size-20)/max(array($diff_x, $diff_z));
$min_x = $min_x*$scale;
$min_z = $min_z*$scale;
$max_x = $max_x*$scale;
$max_z = $max_z*$scale;
$diff_x = $max_x - $min_x;
$diff_z = $max_z - $min_z;
$x_adjustment = abs($min_x)+10+((($image_size-20)-$diff_x)/2);
$z_adjustment = abs($max_z)+10+((($image_size-20)-$diff_z)/2);
}
foreach ($faces as $face)
{
$polygon = array();
foreach ($face as $point)
{
$x = $point['x'];
$z = $point['z'];
$x = $x*$scale;
$z = $z*$scale;
$x = ($x+$x_adjustment);
$z = ($z_adjustment-$z);
$polygon[] = $x;
$polygon[] = $z;
}
if (isset($box['fill']) && $box['fill'] === true)
{
imagefilledpolygon($image, $polygon, 4, $orange);
}
else
{
$color = $green;
if (isset($box['color'])) $color = $box['color'];
imagepolygon($image, $polygon, 4, $color);
}
}
}
imagepng($image, './image.png');
imagedestroy($image);
return true;
}
// THE FIRST BOX SHOULD BE YOUR LARGEST. IF ANY ARE FILLED, PUT THOSE NEXT
$boxes = array();
$boxes[] = array('start' => array(0, 0, 0), 'width' => 80, 'length' => 55, 'height' => 80);
$boxes[] = array('start' => array(40, 0, 0), 'width' => 15, 'length' => 40, 'height' => 80, 'fill' => true);
$boxes[] = array('start' => array(0, 0, 0), 'width' => 40, 'length' => 40, 'height' => 40);
$boxes[] = array('start' => array(0, 0, 40), 'width' => 30, 'length' => 20, 'height' => 40);
// THE FUNCTION ADDS A 20 PIXEL PADDING TO THE IMAGE SO THE TRUE SIZE IS 400
draw_boxes('./image.png', 420, $boxes);
?>
<img src="image.png">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment