ch3/ch3-02 #187
Replies: 11 comments 1 reply
-
纯新手,感觉练习好难啊!有没有答案什么的 |
Beta Was this translation helpful? Give feedback.
-
3.4
|
Beta Was this translation helpful? Give feedback.
-
练习3.2: package main
import (
"fmt"
"math"
)
const (
width, height = 600, 320
cells = 100
xyrange = 30.0
xyscale = width / 2 / xyrange
zscale = height * 0.4
angle = math.Pi / 6
)
var sin30, cos30 = math.Sin(angle), math.Cos(angle)
func main() {
fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+
"style='stroke: grey; fill: white; stroke-width: 0.7' "+
"width='%d' height='%d'>", width, height)
for i := 0; i < cells; i++ {
for j := 0; j < cells; j++ {
ax, ay, az := corner(i+1, j)
bx, by, bz := corner(i, j)
cx, cy, cz := corner(i, j+1)
dx, dy, dz := corner(i+1, j+1)
avgZ := (az + bz + cz + dz) / 4
maxZ := 1.
minZ := -1 / math.Pi
relativeZ := int32(math.Round((avgZ - minZ) / (maxZ - minZ) * 255))
color := (relativeZ << 16) | (255 - relativeZ)
fmt.Printf("<polygon points='%g,%g %g,%g %g,%g %g,%g' fill='#%6x'/>\n",
ax, ay, bx, by, cx, cy, dx, dy, color)
}
}
fmt.Println("</svg>\n")
}
func corner(i, j int) (float64, float64, float64) {
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
z := f(x, y)
sx := width/2 + (x-y)*cos30*xyscale
sy := height/2 + (x+y)*sin30*xyscale - z*zscale
return sx, sy, z
}
func f(x, y float64) float64 {
r := math.Hypot(x, y)
return math.Sin(r) / r
} |
Beta Was this translation helpful? Give feedback.
-
练习3.1 // Surface computes an SVG rendering of a 3-D surface function. import ( const ( var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°) func main() {
} func corner(i, j int) (float64, float64) {
} func f(x, y float64) float64 { func line_intersect(line1 []float64, line2 []float64) bool {
} |
Beta Was this translation helpful? Give feedback.
-
/* // Surface computes an SVG rendering of a 3-D surface function. import ( type GenFunc func(float64, float64) float64 const ( var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°) func main() { func handle(res http.ResponseWriter, req *http.Request) {
} func corner(i, j int, key string) (float64, float64) {
} func f(x, y float64) float64 { func eggBox(x, y float64) float64 { func saddle(x, y float64) float64 { func moguls(x, y float64) float64 { |
Beta Was this translation helpful? Give feedback.
-
3.3 import ( const ( var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°) func main() {
} func corner(i, j int, zValues [][]float64) (float64, float64) {
} func f(x, y float64) float64 { func getColor(z, minZ, maxZ float64) string { // 鸡蛋盒函数 (Eggbox) // 雪坡函数 (Moguls) // 马鞍面 (Saddle) |
Beta Was this translation helpful? Give feedback.
-
3.4 import ( func main() { func handler(w http.ResponseWriter, r *http.Request) { const ( var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°) func svgplot(w io.Writer) {
} func corner(i, j int, zValues [][]float64) (float64, float64) {
} func f(x, y float64) float64 { func getColor(z, minZ, maxZ float64) string { // 鸡蛋盒函数 (Eggbox) // 雪坡函数 (Moguls) // 马鞍面 (Saddle) |
Beta Was this translation helpful? Give feedback.
-
练习3.1bool 表示该点是否合法。如果 z 是 NaN 或 Inf,就跳过这个点。 func corner(i, j int) (float64, float64, bool) {
// Find point (x,y) at corner of cell (i,j).
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
// Compute surface height z.
z := f(x, y)
// 检查 z 是否为合法数字
if math.IsInf(z, 0) || math.IsNaN(z) {
return 0, 0, false
}
// Project (x,y,z) isometrically onto 2-D SVG canvas (sx,sy).
sx := width/2 + (x-y)*cos30*xyscale
sy := height/2 + (x+y)*sin30*xyscale - z*zscale
return sx, sy, true
} |
Beta Was this translation helpful? Give feedback.
-
练习3.2// egg box
func fEggBox(x, y float64) float64 {
return math.Sin(x) * math.Sin(y)
}
func fMoguls(x, y float64) float64 {
return math.Cos(x) + math.Cos(y)
}
func fSaddle(x, y float64) float64 {
return (x*x - y*y) / 40
} |
Beta Was this translation helpful? Give feedback.
-
练习3.3上色Fill 属性 <rect x="10" y="10" width="50" height="50" fill="#ff0000" /> 预计算全局极值在生成图形前,先遍历所有格点计算 z 值,更新全局最小(minZ)和最大(maxZ)值,这样后续对颜色映射时能够正确归一化 z 值。最后算出来的浮点数取两位拼接到字符串当中去 package main
import (
"fmt"
"math"
)
const (
width, height = 600, 320 // 画布尺寸(像素)
cells = 100 // 网格单元数
xyrange = 30.0 // 轴范围(-xyrange..+xyrange)
xyscale = width / 2 / xyrange // 每个 x 或 y 单位对应的像素数
zscale = height * 0.4 // 每个 z 单位对应的像素数
angle = math.Pi / 6 // x, y 轴的角度(30°)
)
var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°) 与 cos(30°)
var minZ, maxZ float64 = math.Inf(1), math.Inf(-1) // 全局 z 值极值
func main() {
// 第一遍遍历:预先计算所有角点的 z 值,更新全局 minZ 和 maxZ
for i := 0; i <= cells; i++ {
for j := 0; j <= cells; j++ {
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
z := f(x, y)
if math.IsInf(z, 0) || math.IsNaN(z) {
continue
}
if z < minZ {
minZ = z
}
if z > maxZ {
maxZ = z
}
}
}
// 输出 SVG 文件头
fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+
"style='stroke: grey; fill: white; stroke-width: 0.7' "+
"width='%d' height='%d'>\n", width, height)
// 第二遍遍历:绘制每个单元格对应的多边形
for i := 0; i < cells; i++ {
for j := 0; j < cells; j++ {
ax, ay, az, ok1 := corner(i+1, j)
bx, by, bz, ok2 := corner(i, j)
cx, cy, cz, ok3 := corner(i, j+1)
dx, dy, dz, ok4 := corner(i+1, j+1)
if ok1 && ok2 && ok3 && ok4 {
avgZ := (az + bz + cz + dz) / 4
color := colorForZ(avgZ)
fmt.Printf("<polygon points='%g,%g %g,%g %g,%g %g,%g' fill='%s'/>\n",
ax, ay, bx, by, cx, cy, dx, dy, color)
}
}
}
fmt.Println("</svg>")
}
// 根据 z 值生成颜色(归一化后,z 越高颜色越红,越低则越蓝)
func colorForZ(z float64) string {
norm := (z - minZ) / (maxZ - minZ)
r := int(255 * norm)
b := int(255 * (1 - norm))
return fmt.Sprintf("#%02x00%02x", r, b)
}
// 计算格点 (i,j) 对应的 2D 投影坐标及其高度 z
func corner(i, j int) (float64, float64, float64, bool) {
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
z := f(x, y)
if math.IsInf(z, 0) || math.IsNaN(z) {
return 0, 0, 0, false
}
sx := width/2 + (x-y)*cos30*xyscale
sy := height/2 + (x+y)*sin30*xyscale - z*zscale
return sx, sy, z, true
}
func f(x, y float64) float64 {
r := math.Hypot(x, y)
return math.Sin(r) / r
} |
Beta Was this translation helpful? Give feedback.
-
练习3.4主要修改点 在于 http.ResponseWriter fmt.Fprintf(w, ...) 把内容“格式化”并写到 io.Writer(比如 HTTP 响应)。 类似于 printf,但目标是写入到 w 而不是终端。 package main
import (
"fmt"
"io"
"math"
"net/http"
)
func main() {
printURL("http://localhost:8080/svg") // 打印访问地址
http.HandleFunc("/svg", handler)
http.ListenAndServe(":8080", nil)
}
func printURL(url string) {
fmt.Println("服务已启动,访问以下地址查看 SVG 图像:")
fmt.Println(url)
}
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
Surface(w)
}
const (
width, height = 600, 320
cells = 100
xyrange = 30.0
xyscale = width / 2 / xyrange
zscale = height * 0.4
angle = math.Pi / 6
)
var sin30, cos30 = math.Sin(angle), math.Cos(angle)
var minZ, maxZ float64 = math.Inf(1), math.Inf(-1)
func Surface(w io.Writer) {
for i := 0; i <= cells; i++ {
for j := 0; j <= cells; j++ {
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
z := f(x, y)
if math.IsInf(z, 0) || math.IsNaN(z) {
continue
}
if z < minZ {
minZ = z
}
if z > maxZ {
maxZ = z
}
}
}
fmt.Fprintf(w, "<svg xmlns='http://www.w3.org/2000/svg' "+
"style='stroke: grey; fill: white; stroke-width: 0.7' "+
"width='%d' height='%d'>\n", width, height)
for i := 0; i < cells; i++ {
for j := 0; j < cells; j++ {
ax, ay, az, ok1 := corner(i+1, j)
bx, by, bz, ok2 := corner(i, j)
cx, cy, cz, ok3 := corner(i, j+1)
dx, dy, dz, ok4 := corner(i+1, j+1)
if ok1 && ok2 && ok3 && ok4 {
avgZ := (az + bz + cz + dz) / 4
color := colorForZ(avgZ)
fmt.Fprintf(w, "<polygon points='%g,%g %g,%g %g,%g %g,%g' fill='%s'/>\n",
ax, ay, bx, by, cx, cy, dx, dy, color)
}
}
}
fmt.Fprintln(w, "</svg>")
}
func colorForZ(z float64) string {
norm := (z - minZ) / (maxZ - minZ)
r := int(255 * norm)
b := int(255 * (1 - norm))
return fmt.Sprintf("#%02x00%02x", r, b)
}
func corner(i, j int) (float64, float64, float64, bool) {
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
z := f(x, y)
if math.IsInf(z, 0) || math.IsNaN(z) {
return 0, 0, 0, false
}
sx := width/2 + (x-y)*cos30*xyscale
sy := height/2 + (x+y)*sin30*xyscale - z*zscale
return sx, sy, z, true
}
func f(x, y float64) float64 {
r := math.Hypot(x, y)
return math.Sin(r) / r
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
ch3/ch3-02
中文版
https://golang-china.github.io/gopl-zh/ch3/ch3-02.html
Beta Was this translation helpful? Give feedback.
All reactions