Skip to content

Instantly share code, notes, and snippets.

@vladfil
Created October 13, 2017 15:04
Show Gist options
  • Select an option

  • Save vladfil/9232e85dcb145aa9a3f332b545bd3231 to your computer and use it in GitHub Desktop.

Select an option

Save vladfil/9232e85dcb145aa9a3f332b545bd3231 to your computer and use it in GitHub Desktop.
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