From Gossip@caterpillar

Computer Graphics: 最大最小法

 

 


在 函式圖形繪製 的範例中,發現到有一些座標點必須是被遮蓋住,而不應被繪製出來的。

在處理隱藏面的問題時,必須根據繪製圖形來決定不同的方法,對於單純的座標點繪製,可以使用簡單的最大最小法來讓被遮蓋的座標點不被繪製。

最大最小法的原理很簡單,繪製時必須從最接近我們的點開始繪製,也就是由最大的Z座標點開始繪製;最大最小點是根據Y座標的值來決定哪些點應該被繪製,假設繪製圖形時是使用以下的迴圈:
 for(z = 200; z >= -200; z-=10) {
    for(x = -200; x <= 200; x++) {
        //計算座標並繪點
        ....
    }
 }


假設前三次繪圖在Y的坡度上是漸增的,如下所示:


必須記錄每一個x位置上的ymax與ymin,如果在第四次繪製時某些位置上的Y坡度是下降的,則那些位置上的Y必然是位於ymax與ymin之間,此時這些點可以不繪製,如下圖所示:



記得在一開始必須將ymax設定為最小的Y值,ymin設定為最大的Y值;以下是將函式繪圖中的範例應用最大最小法繪製的方法與結果:

  • MaxMinMethodDemo.java
package onlyfun.caterpillar;

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

public class MaxMinMethodDemo extends JApplet {
private int orgX;
private int orgY;
private int[] ymax, ymin;

public void init() {
super.init();
setBackground(Color.black);
orgX = (int)getSize().width /2;
orgY = (int) (getSize().height / 2);
ymax = new int[600];
ymin = new int[600];
}

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

// 重置最大最小點
for(int i = 0; i < 600; i++) {
ymax[i] = 0;
ymin[i] = 600;
}

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

for(int z = 200; z >= -200; z-=10) {
for(int x = -200; x <= 200; x++) {
double y = 30*(Math.cos(
Math.toRadians(
Math.sqrt(x*x+z*z)))
+ Math.cos(
Math.toRadians(3 *
Math.sqrt(x*x+z*z)));

// 立體旋轉,從斜角繪製,調整繪圖中心至視窗中心
int pointX = (int) (orgX + x*Math.cos(angleY) +
z*Math.sin(angleY));
int pointY = (int) (orgY - (y*Math.cos(angleX) -
(-x*Math.sin(angleY) +
z*Math.cos(angleY)) *
Math.sin(angleX)));

// 最大最小法
if(pointY < ymin[pointX]) {
ymin[pointX] = pointY;
g.drawLine(pointX, pointY, pointX, pointY);
}

if(pointY > ymax[pointX]) {
ymax[pointX] = pointY;
g.drawLine(pointX, pointY, pointX, pointY);
}
}
}
}
}