2017-07-11 191 views
1

我正在嘗試查找將(x,y,z)轉換爲(x,y)所需的數學運算,以便可以使用php創建框。所有點將在網格上,並且沒有旋轉。將3D對象轉換爲2D空間

我已經嘗試了這種解決方案https://stackoverflow.com/a/25955134/379249這讓我的存在方式的一部分,但我需要弄清楚的多邊形

。例如點,我在下面紅色顯示一個大箱子。

boxes

我需要能夠給它要麼寬度,長度,高度的尺寸和起點或我可以給它的所有四個點構成每個面上。

我需要翻譯那些使它看起來3D,這是我絆倒了。

一旦紅色框被創建,我也需要能夠使用相同的功能,如綠色,藍色或橙色創建其他框。

我可以創建代碼,但我堅持數學來做翻譯。

任何想法?

謝謝!

編輯 **

感謝@ user2464424我能得到它非常接近。以下是我的代碼。

和我生成的圖像。

<?php 
function RotatePoint($sin,$cos,$x,$y) { 
    return array($x*$cos - $y*$sin, $y*$cos + $x*$sin); 
} 

$im = imagecreatetruecolor(200, 200); 

$white = imagecolorallocate($im, 255, 255, 255); 
imagefilledrectangle($im, 0, 0, 200, 200, $white); 

$brown = imagecolorallocate($im, 120, 53, 31); 
$green = imagecolorallocate($im, 23, 255, 65); 
$blue = imagecolorallocate($im, 31, 23, 255); 
$orange = imagecolorallocate($im, 255, 185, 23); 

function draw_box(&$image, $color, $start, $width, $length, $height) 
{ 
    $camx = 80; 
    $camy = 240; 
    $camz = 40; 

    $yaw = 10; 
    $pitch = 20; 
    $sy = sin(-$yaw); $cy = cos(-$yaw); $sp = sin(-$pitch); $cp = cos(-$pitch); 

    $start_x = $start[0]; 
    $start_y = $start[1]; 
    $start_z = $start[2]; 

    // 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; 
     } 


     $polygon = array(); 
     foreach ($face as $point) 
     { 
      $x = $point[0] - $camx; 
      $y = $point[1] - $camy; 
      $z = $point[2] - $camz; 

      $rot = RotatePoint($sy,$cy,$x,$y); 
      $x = $rot[0]; 
      $y = $rot[1]; 

      $rot = RotatePoint($sp,$cp,$z,$y); 
      $z = $rot[0]; 
      $y = $rot[1]; 

      $polygon[] = $x; 
      $polygon[] = $z; 
     } 

     imagepolygon($image, $polygon, 4, $color); 
    } 
} 

draw_box($im, $brown, array(0, 0, 0), 80, 80, 80); 

draw_box($im, $green, array(0, 0, 0), 40, 40, 40); 

draw_box($im, $blue, array(0, 0, 40), 30, 20, 10); 

draw_box($im, $orange, array(60, 0, 0), 15, 40, 80); 

imagepng($im, './image.png'); 

imagedestroy($im); 
?> 
<img src="image.png"> 

enter image description here

一對夫婦的問題。

1:我如何從底部獲取軸的原點,現在它在右側倒過來。

2:說我總是想在400x400的圖像上生成它,我如何確保它不會脫落或能夠放大?

3:如果容器是40x40x40或10x100x100,我如何調整原點,使其始終位於圖像的底部,並且盒子的比例尺適合?

編輯 **

下面是最終代碼的鏈接: https://gist.github.com/rzfarrell/3a9e5046dcfd6bd2d2f4bfa1a34b21ef

,使此: enter image description here

+1

我認爲你想要實現的是正射投影,這是正確的嗎? – user2464424

+2

有* bazillions *的方式投影3D到2D。如果您還沒有,請查看:https://en.wikipedia.org/wiki/Graphical_projection。此外,翻譯很容易(只需做x'= x + delta等)。輪換更難:https://en.wikipedia.org/wiki/Rotation_(mathematics) –

+0

@ user2464424是正射投影是我正在尋找。 – bones

回答

1

對一個三維點的正投影的主要思想3D空間中的免費攝像頭是移動和旋轉攝像頭,使其最終以a)爲中心,b)不旋轉。值得一提的是,組成3D世界的所有要點必須嚴格按照相機進行轉換。

這通常歸結爲一個兩步過程:

1)首先,通過反相原點相機向量平移該點:然後

$x = $pointx - $camx; $y = $pointy - $camy; $z = $pointz - $camz; 

2),圍繞所述旋轉點由相機的俯仰角和偏航角取反(可能以弧度表示):

$sy = sin(-$yaw); $cy = cos(-$yaw); $sp = sin(-$pitch); $cp = cos(-$pitch); 

function RotatePoint($sin,$cos,$x,$y) { 
    return array($x*$cos - $y*$sin, $y*$cos + $x*$sin); 
} 

$rot = RotatePoint($sy,$cy,$x,$y); 
$x = $rot[0]; 
$y = $rot[1]; 

$rot = RotatePoint($sp,$cp,$z,$y); 
$z = $rot[0]; 
$y = $rot[1]; 

然後你就完成了。現在,$x$z表示距相機中心的相機平面中的2D點的座標,並且$y是該點與相機平面的垂直距離。

如果您想要輸出圖片,您可能需要縮放和限制座標以適應圖像大小,這很平凡。你必須考慮的一件事是忽略所有具有y<=0的點,因爲這意味着它們位於相機後面。

+0

謝謝!我已經得到了一些工作代碼,並用它更新了我的問題,但仍有一些問題需要解決。 – bones

+1

@bones不客氣,但要多加註意,有些地方有混亂。首先,攝像機的方向角應該是弧度。使用['deg2rad'](http://php.net/manual/en/function.deg2rad.php)功能進行轉換。然後,請記住,一旦點座標轉換後,您就可以隨心所欲地做任何事情。例如,您可以否定'$ z'來顛倒結果。另外,因爲'screen'是左上角有一個(0,0)的圖像,所以你想添加一個像'= $ CanvasHalfWidth + $ x;'和'= $ CanvasHalfHeight- $ z;' – user2464424

+1

@骨骼爲了縮放,您還可以將'$ x'和'$ z'乘以一些可以稱爲縮放的因子。一旦你做了修改嘗試相機的位置(-25,-50,100)偏航= deg2rad(-35)和俯仰= deg2rad(35)。我嘗試了這些參數,並得到了一個或多或少中心的圖像。 – user2464424