package dem import ( "math" "github.com/airbusgeo/godal" log "github.com/sirupsen/logrus" ) type Dem1Km struct { File string LT [][]float32 width, height int wUnit float32 // degree per pixel hUnit float32 // degree per pixel } var Dem1KmLT *Dem1Km func NewDem1Km(file string) *Dem1Km { d := &Dem1Km{ File: file, } if err := d.Load(); err != nil { log.Error("cannot load DEM file", err) } return d } func (d *Dem1Km) Load() error { hDataset, err := godal.Open(d.File) if err != nil { return err } band := hDataset.Bands()[0] structure := band.Structure() for y := 0; y < structure.SizeY; y++ { scanline := make([]float32, structure.SizeX) err = band.Read(0, y, scanline, structure.SizeX, 1) if err != nil { return err } d.LT = append(d.LT, scanline) } d.wUnit = 360.0 / float32(structure.SizeX) d.hUnit = 180.0 / float32(structure.SizeY) d.width = structure.SizeX d.height = structure.SizeY hDataset.Close() log.Infof("DEM loaded: %s, %d x %d, wUnit: %.2f, hUnit: %.2f", d.File, d.width, d.height, d.wUnit, d.hUnit) return nil } func (d *Dem1Km) Elevation(lng, lat float64) float32 { lng = math.Abs(lng + 180.0) lat = math.Abs(lat - 90.0) w := int(lng / float64(d.wUnit)) h := int(lat / float64(d.hUnit)) if w > d.width-1 || h > d.height-1 { return 0.0 } return d.LT[h][w] } func (d *Dem1Km) MinMaxElevationInRect(lng1, lat1, lng2, lat2 float64) (float64, float64) { minElev := math.MaxFloat32 maxElev := -math.MaxFloat32 lng1 = math.Abs(lng1 + 180.0) lat1 = math.Abs(lat1 - 90.0) w1 := int(lng1 / float64(d.wUnit)) h1 := int(lat1 / float64(d.hUnit)) lng2 = math.Abs(lng2 + 180.0) lat2 = math.Abs(lat2 - 90.0) w2 := int(lng2 / float64(d.wUnit)) h2 := int(lat2 / float64(d.hUnit)) if w1 > d.width-1 || h1 > d.height-1 || w2 > d.width-1 || h2 > d.height-1 { return 0.0, 0.0 } for w := w1; w <= w2; w++ { for h := h1; h <= h2; h++ { if d.LT[h][w] < float32(minElev) { minElev = float64(d.LT[h][w]) } if d.LT[h][w] > float32(maxElev) { maxElev = float64(d.LT[h][w]) } } } return minElev, maxElev }