From Gossip@caterpillar

Computer Graphics: 旋轉體、錐狀體、柱狀體頂點

 

 


由於旋轉體、錐狀體、柱狀體的幾何性質,使得它們的頂點配置具有規則而容易以運算來進行配置,觀念上十分簡單。

旋轉體

假設旋轉體是繞著Y軸旋轉,則可以先定義出一條錂線上的頂點,與它們各自距Y軸的距離,接下來只要旋轉這些頂點,就可以得出旋轉體所有的頂點,如下所示:


真實世界中的旋轉體很多,所以這個方法可以畫出各種不同的旋轉體;下面這個程式畫出一個高腳杯,它不儲存頂點,而直接利用運算後的頂點來繪製酒杯的骨架,採取的方法是先用迴圈畫圈圈,再由一次迴圈來畫錂線:
  • VetexDemo.java
package onlyfun.caterpillar;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JApplet;

public class VetexDemo extends JApplet {
private int orgX;
private int orgY;

public void init() {
super.init();
setBackground(Color.black);
orgX = (int)getSize().width / 3;
orgY = (int) (getSize().height - 80);
}

public void paint(Graphics g) {
g.setColor(Color.yellow);

double[] yLocations =
{180, 140, 100, 60, 20, 10, 4, 0};
double[] rDistances =
{100, 55, 10, 10, 10, 50, 80, 80};

// 從斜角繪製
// 繞 x 軸轉 30 度,繞 z 軸轉 -25 度
double angleX = Math.toRadians(30);
double angleZ = Math.toRadians(-25);

// 360 度畫圈
for(int i = 0; i < yLocations.length; i++) {
// 我們要畫線段,所以求出第一點不用畫
double x = rDistances[i] * Math.cos(0);
double z = rDistances[i] * Math.sin(0);

int lineStartX = (int) (orgX +
xAfterRotateAroundXZ(x, yLocations[i],
z, angleX, angleZ));
int lineStartY = (int) (orgY -
yAfterRotateAroundXZ(x, yLocations[i],
z, angleX, angleZ));

for(int j = 1; j <= 360; j += 10) {
// 計算 x, z 座標
x = rDistances[i]
* Math.cos(Math.toRadians(j));
z = rDistances[i]
* Math.sin(Math.toRadians(j));

// 立體旋轉,從斜角繪製,調整繪圖中心至視窗中心
int lineEndX = (int) (orgX +
xAfterRotateAroundXZ(x, yLocations[i],
z, angleX, angleZ));
int lineEndY = (int) (orgY -
yAfterRotateAroundXZ(x, yLocations[i],
z, angleX, angleZ));

g.drawLine(lineStartX, lineStartY,
lineEndX, lineEndY);
lineStartX = lineEndX;
lineStartY = lineEndY;
}
}

// 畫錂線
for(int j = 0; j <= 360; j+=60) {
// 我們要畫線段,所以求出第一點不用畫
double x = rDistances[0] *
Math.cos(Math.toRadians(j));
double z = rDistances[0] *
Math.sin(Math.toRadians(j));

int lineStartX = (int) (orgX +
xAfterRotateAroundXZ(x, yLocations[0],
z, angleX, angleZ));
int lineStartY = (int) (orgY -
yAfterRotateAroundXZ(x, yLocations[0],
z, angleX, angleZ));

for(int i = 1; i < yLocations.length; i++) {
x = rDistances[i] *
Math.cos(Math.toRadians(j));
z = rDistances[i] *
Math.sin(Math.toRadians(j));

// 立體旋轉,從斜角繪製,調整繪圖中心至視窗中心
int lineEndX = (int) (orgX +
xAfterRotateAroundXZ(x, yLocations[i],
z, angleX, angleZ));
int lineEndY = (int) (orgY -
yAfterRotateAroundXZ(x, yLocations[i],
z, angleX, angleZ));

g.drawLine(lineStartX, lineStartY,
lineEndX, lineEndY);
lineStartX = lineEndX;
lineStartY = lineEndY;
}
}
}

private double xAfterRotateAroundXZ(double x, double y,
double z, double angleX, double angleZ) {
return (x*Math.cos(angleZ) -
(y*Math.cos(angleX) - z*Math.sin(angleX))
* Math.sin(angleZ));
}

private double yAfterRotateAroundXZ(double x, double y,
double z, double angleX, double angleZ) {
return (x*Math.sin(angleZ) +
(y*Math.cos(angleX) - z*Math.sin(angleX))
* Math.cos(angleZ));
}
}

上面這個Applet的繪圖結果如下:


錐狀體

錐狀體將底面所有的頂點放置在XZ平面上,底面與錐頂點的交點為(xc, 0, yc),高度為h,則錐頂點的座標為(xc, h, yc),如下所示:

柱狀體

柱狀體將底面所有的頂點放置在XZ平面上,高度為h,則頂點座標配置如下所示: