Created
October 13, 2017 15:04
-
-
Save vladfil/9232e85dcb145aa9a3f332b545bd3231 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import( | |
| "os" | |
| "math" | |
| "strconv" | |
| ) | |
| const ( | |
| width, height = 600, 320 // canvas size in pixels | |
| cells = 20 // number of grid cells | |
| xyrange = 30.0 // axis ranges (-xyrange..+xyrange) | |
| xyscale = width / 2 / xyrange // pixels per x or y unit | |
| zscale = height * 0.4 // pixels per z unit | |
| angle = math.Pi / 6 // angle of x, y axes (=30°) | |
| ) | |
| var sin30, cos30 = math.Sin(angle), math.Cos(angle) | |
| func main() { | |
| colorsSlice := []string{"#FF0000", "#F2000D", "#E6001A", "#D90026", "#CC0033", "#BF0040", "#B2004C", "#A60059", "#990066", "#8C0073", "#800080", "#73008C", "#660099", "#5900A6", "#4D00B2", "#4000BF", "#3300CC", "#2600D9", "#1900E6", "#0D00F2", "#0000FF"} | |
| var minHeight float64 = 1000 | |
| var maxHeight float64 = 1 | |
| // Find max and min height values | |
| for i := 0; i < cells; i++ { | |
| for j := 0; j < cells; j++ { | |
| _, ay := corner(i+1, j) | |
| _, by := corner(i, j) | |
| _, cy := corner(i, j+1) | |
| _, dy := corner(i+1, j+1) | |
| switch { | |
| case minHeight > ay: | |
| minHeight = ay | |
| case minHeight > by: | |
| minHeight = by | |
| case minHeight > cy: | |
| minHeight = cy | |
| case minHeight > dy: | |
| minHeight = dy | |
| } | |
| switch { | |
| case maxHeight < ay: | |
| maxHeight = ay | |
| case maxHeight < by: | |
| maxHeight = by | |
| case maxHeight < cy: | |
| maxHeight = cy | |
| case maxHeight < dy: | |
| maxHeight = dy | |
| } | |
| } | |
| } | |
| heightStep := (maxHeight - minHeight)/float64(cells) | |
| str := "<svg xmlns='http://www.w3.org/2000/svg' style='stroke: grey; fill: white; stroke-width: 0.7' width='"+ string(width) +"' height='"+string(height) +"'>" | |
| for i := 0; i < cells; i++ { | |
| for j := 0; j < cells; j++ { | |
| ax, ay := corner(i+1, j) | |
| bx, by := corner(i, j) | |
| cx, cy := corner(i, j+1) | |
| dx, dy := corner(i+1, j+1) | |
| maxY := getMax(ay, by, cy, dy) | |
| colorStepNum := int (maxY/heightStep) - 1 | |
| color := colorsSlice[colorStepNum] | |
| // fmt.Println(color) | |
| str += "<polygon points='"+floatToString(ax)+","+floatToString(ay)+","+floatToString(bx)+","+floatToString(by)+","+floatToString(cx)+","+floatToString(cy)+","+floatToString(dx)+","+floatToString(dy)+"' fill='"+ color +"'/>\n" | |
| } | |
| } | |
| str += "</svg>" | |
| fi, err := os.Open("canvas.svg") | |
| if err != nil { | |
| fi, createErr := os.Create("canvas.svg") | |
| if createErr != nil { | |
| panic(createErr) | |
| } | |
| fi.WriteString( str ) | |
| } else { | |
| statFi, err := fi.Stat() | |
| if err != nil { | |
| panic(err) | |
| } else if statFi.Size() > 0 { | |
| fi.Close(); | |
| var err = os.Remove( "canvas.svg" ) | |
| if err != nil { | |
| panic(err) | |
| } | |
| createFile("canvas.svg", str) | |
| } else { | |
| if statFi.Size() == 0 { | |
| fi.Close(); | |
| var err = os.Remove( "canvas.svg" ) | |
| if err != nil { | |
| panic(err) | |
| } | |
| createFile("canvas.svg", str) | |
| } | |
| } | |
| } | |
| } | |
| func corner(i, j int) (float64, float64) { | |
| // 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) | |
| // fmt.Println(z) | |
| // 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 | |
| } | |
| func f(x, y float64) float64 { | |
| r := math.Hypot(x, y) // distance from (0,0) | |
| return math.Sin(r) / r | |
| } | |
| func floatToString(input_num float64) string { | |
| // to convert a float number to a string | |
| return strconv.FormatFloat(input_num, 'f', 6, 64) | |
| } | |
| func createFile(fileName, str string) { | |
| fi, createErr := os.Create(fileName) | |
| if createErr != nil { | |
| panic(createErr) | |
| } | |
| fi.WriteString( str ) | |
| fi.Close() | |
| } | |
| func getMax(ns ... float64) float64 { | |
| var max float64 | |
| for _, v := range ns{ | |
| if max < v { | |
| max = v | |
| } | |
| } | |
| return max | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment