comparison pkg/octree/tin.go @ 968:a4fe07a21ba7

Moved octree builder into octree package to be reusable by the sounding result import job.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 17 Oct 2018 16:00:49 +0200
parents
children f9fb6c399f3f
comparison
equal deleted inserted replaced
967:2025074ad835 968:a4fe07a21ba7
1 package octree
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "errors"
7 "fmt"
8 "io"
9 "log"
10 "math"
11 )
12
13 var (
14 errNoByteSlice = errors.New("Not a byte slice")
15 errTooLessPoints = errors.New("Too less points")
16 )
17
18 const wgs84 = 4326
19
20 type Tin struct {
21 EPSG uint32
22 Vertices []Vertex
23 Triangles [][]int32
24
25 Min Vertex
26 Max Vertex
27 }
28
29 func (t *Tin) FromWKB(data []byte) error {
30 log.Printf("data length %d\n", len(data))
31
32 r := bytes.NewReader(data)
33
34 endian, err := r.ReadByte()
35
36 var order binary.ByteOrder
37
38 switch {
39 case err != nil:
40 return err
41 case endian == wkbNDR:
42 order = binary.LittleEndian
43 case endian == wkbXDR:
44 order = binary.BigEndian
45 default:
46 return fmt.Errorf("unknown byte order %x", endian)
47 }
48
49 var geomType uint32
50 err = binary.Read(r, order, &geomType)
51
52 switch {
53 case err != nil:
54 return err
55 case geomType != wkbTinZ:
56 return fmt.Errorf("unknown geometry type %x", geomType)
57 }
58
59 var num uint32
60 if err = binary.Read(r, order, &num); err != nil {
61 return err
62 }
63
64 vertices := make([]Vertex, 0, 100000)
65
66 var v Vertex
67
68 v2i := make(map[Vertex]int32, 100000)
69
70 var indexPool []int32
71
72 allocIndices := func() []int32 {
73 if len(indexPool) == 0 {
74 indexPool = make([]int32, 3*8*1024)
75 }
76 ids := indexPool[:3]
77 indexPool = indexPool[3:]
78 return ids
79 }
80
81 var triangles [][]int32
82
83 min := Vertex{math.MaxFloat64, math.MaxFloat64, math.MaxFloat64}
84 max := Vertex{-math.MaxFloat64, -math.MaxFloat64, -math.MaxFloat64}
85
86 for i := uint32(0); i < num; i++ {
87
88 endian, err = r.ReadByte()
89 switch {
90 case err != nil:
91 return err
92 case endian == wkbNDR:
93 order = binary.LittleEndian
94 case endian == wkbXDR:
95 order = binary.BigEndian
96 default:
97 return fmt.Errorf("unknown byte order %x", endian)
98 }
99
100 err = binary.Read(r, order, &geomType)
101 switch {
102 case err != nil:
103 return err
104 case geomType != wkbTriangleZ:
105 return fmt.Errorf("unknown geometry type %d", geomType)
106 }
107
108 var rings uint32
109 if err = binary.Read(r, order, &rings); err != nil {
110 return err
111 }
112 triangle := allocIndices()
113
114 for ring := uint32(0); ring < rings; ring++ {
115 var npoints uint32
116 if err = binary.Read(r, order, &npoints); err != nil {
117 return err
118 }
119
120 if npoints < 3 {
121 return errTooLessPoints
122 }
123
124 for p := uint32(0); p < npoints; p++ {
125 var x, y, z uint64
126 for _, addr := range []*uint64{&x, &y, &z} {
127 if err = binary.Read(r, order, addr); err != nil {
128 return err
129 }
130 }
131 if p >= 3 || ring >= 1 {
132 // Don't store the forth point.
133 continue
134 }
135 // Do this conversion later to spare reflect calls
136 // and allocs in binary.Read.
137 v.X = math.Float64frombits(x)
138 v.Y = math.Float64frombits(y)
139 v.Z = math.Float64frombits(z)
140 idx, found := v2i[v]
141 if !found {
142 idx = int32(len(vertices))
143 v2i[v] = idx
144 vertices = append(vertices, v)
145 min.Minimize(v)
146 max.Maximize(v)
147 }
148 triangle[p] = idx
149 }
150 }
151 triangles = append(triangles, triangle)
152 }
153
154 log.Printf("bbox: [[%f, %f], [%f, %f]]\n",
155 min.X, min.Y, max.X, max.Y)
156
157 *t = Tin{
158 EPSG: wgs84,
159 Vertices: vertices,
160 Triangles: triangles,
161 Min: min,
162 Max: max,
163 }
164
165 return nil
166 }
167
168 func (t *Tin) Scan(raw interface{}) error {
169
170 data, ok := raw.([]byte)
171 if !ok {
172 return errNoByteSlice
173 }
174 return t.FromWKB(data)
175 }
176
177 func (t *Tin) Serialize(w io.Writer) error {
178
179 if err := binary.Write(w, binary.LittleEndian, t.EPSG); err != nil {
180 return err
181 }
182
183 if err := t.Min.Write(w); err != nil {
184 return err
185 }
186 if err := t.Max.Write(w); err != nil {
187 return err
188 }
189
190 if err := binary.Write(
191 w, binary.LittleEndian, uint32(len(t.Vertices))); err != nil {
192 return err
193 }
194
195 for _, v := range t.Vertices {
196 if err := v.Write(w); err != nil {
197 return err
198 }
199 }
200 log.Printf("vertices %d (%d)\n", len(t.Vertices), len(t.Vertices)*3*8)
201
202 if err := binary.Write(
203 w, binary.LittleEndian, uint32(len(t.Triangles))); err != nil {
204 return err
205 }
206
207 var buf [binary.MaxVarintLen32]byte
208 var written int
209 var last int32
210 for _, triangle := range t.Triangles {
211 for _, idx := range triangle {
212 value := idx - last
213 n := binary.PutVarint(buf[:], int64(value))
214 for p := buf[:n]; len(p) > 0; p = p[n:] {
215 var err error
216 if n, err = w.Write(p); err != nil {
217 return err
218 }
219 written += n
220 }
221 last = idx
222 }
223 }
224 log.Printf("compressed tin indices in bytes: %d (%d)\n",
225 written, 3*4*len(t.Triangles))
226
227 return nil
228 }