Mercurial > gemma
view cmd/soundingresults/points.go @ 616:51dc26b0f066
client: avoid extra password reveal button for IE/Edge
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Tue, 11 Sep 2018 09:50:37 +0200 |
parents | bc2b7da07d60 |
children |
line wrap: on
line source
package main import ( "bufio" "bytes" "compress/bzip2" "compress/gzip" "encoding/binary" "io" "log" "math" "os" "path/filepath" "strconv" "strings" ) type point3d struct { x float64 y float64 z float64 } type points3d []*point3d func parseXYZ(fname string) (points3d, error) { f, err := os.Open(fname) if err != nil { return nil, err } defer f.Close() r, err := wrap(fname, f) if err != nil { return nil, err } return readXYZ(r) } func wrap(fname string, f io.Reader) (io.Reader, error) { switch strings.ToLower(filepath.Ext(fname)) { case ".gz": return gzip.NewReader(f) case ".bz2": return bzip2.NewReader(f), nil } return bufio.NewReader(f), nil } func readXYZ(r io.Reader) (points3d, error) { // Alloc in larger chunks to reduce pressure on memory management. var chunk []point3d alloc := func() *point3d { if len(chunk) == 0 { chunk = make([]point3d, 8*1024) } p := &chunk[0] chunk = chunk[1:] return p } var points points3d s := bufio.NewScanner(r) if s.Scan() { // Skip header line. for line := 2; s.Scan(); line++ { p := alloc() text := s.Text() // fmt.Sscanf(text, "%f,%f,%f") is 4 times slower. idx := strings.IndexByte(text, ',') if idx == -1 { log.Printf("format error in line %d\n", line) continue } var err error if p.x, err = strconv.ParseFloat(text[:idx], 64); err != nil { log.Printf("format error in line %d: %v\n", line, err) continue } text = text[idx+1:] if idx = strings.IndexByte(text, ','); idx == -1 { log.Printf("format error in line %d\n", line) continue } if p.y, err = strconv.ParseFloat(text[:idx], 64); err != nil { log.Printf("format error in line %d: %v\n", line, err) continue } text = text[idx+1:] if p.z, err = strconv.ParseFloat(text, 64); err != nil { log.Printf("format error in line %d: %v\n", line, err) continue } points = append(points, p) } } return points, s.Err() } const ( wkbNDR byte = 1 wkbPointZ uint32 = 1 + 1000 wkbMultiPointZ uint32 = 4 + 1000 ) func (ps points3d) asWKB() string { size := 1 + 4 + 4 + len(ps)*(1+4+3*8) buf := bytes.NewBuffer(make([]byte, 0, size)) binary.Write(buf, binary.LittleEndian, wkbNDR) binary.Write(buf, binary.LittleEndian, wkbMultiPointZ) binary.Write(buf, binary.LittleEndian, uint32(len(ps))) for _, p := range ps { binary.Write(buf, binary.LittleEndian, wkbNDR) binary.Write(buf, binary.LittleEndian, wkbPointZ) binary.Write(buf, binary.LittleEndian, math.Float64bits(p.x)) binary.Write(buf, binary.LittleEndian, math.Float64bits(p.y)) binary.Write(buf, binary.LittleEndian, math.Float64bits(p.z)) } return buf.String() }