comparison cmd/tin2octree/tin.go @ 661:af1d4d44a88a octree

Experimental tin octree indexer.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 18 Sep 2018 00:11:32 +0200
parents
children a3d722e1f593
comparison
equal deleted inserted replaced
660:79db27e3a999 661:af1d4d44a88a
1 package main
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 (
19 wkbXDR byte = 0
20 wkbNDR byte = 1
21 wkbTinZ uint32 = 1000 + 16
22 wkbTriangleZ uint32 = 1000 + 17
23 )
24
25 type tin struct {
26 vertices []vertex
27 triangles [][]int32
28
29 min vertex
30 max vertex
31 }
32
33 func (t *tin) FromWKB(data []byte) error {
34 log.Printf("data length %d\n", len(data))
35
36 r := bytes.NewReader(data)
37
38 endian, err := r.ReadByte()
39
40 var order binary.ByteOrder
41
42 switch {
43 case err != nil:
44 return err
45 case endian == wkbNDR:
46 order = binary.LittleEndian
47 case endian == wkbXDR:
48 order = binary.BigEndian
49 default:
50 return fmt.Errorf("unknown byte order %x", endian)
51 }
52
53 var geomType uint32
54 err = binary.Read(r, order, &geomType)
55
56 switch {
57 case err != nil:
58 return err
59 case geomType != wkbTinZ:
60 return fmt.Errorf("unknown geometry type %x", geomType)
61 }
62
63 var num uint32
64 if err = binary.Read(r, order, &num); err != nil {
65 return err
66 }
67
68 vertices := make([]vertex, 0, 100000)
69
70 var v vertex
71
72 v2i := make(map[vertex]int32, 100000)
73
74 var indexPool []int32
75
76 allocIndices := func() []int32 {
77 if len(indexPool) == 0 {
78 indexPool = make([]int32, 3*8*1024)
79 }
80 ids := indexPool[:3]
81 indexPool = indexPool[3:]
82 return ids
83 }
84
85 var triangles [][]int32
86
87 min := vertex{math.MaxFloat64, math.MaxFloat64, math.MaxFloat64}
88 max := vertex{-math.MaxFloat64, -math.MaxFloat64, -math.MaxFloat64}
89
90 for i := uint32(0); i < num; i++ {
91
92 endian, err = r.ReadByte()
93 switch {
94 case err != nil:
95 return err
96 case endian == wkbNDR:
97 order = binary.LittleEndian
98 case endian == wkbXDR:
99 order = binary.BigEndian
100 default:
101 return fmt.Errorf("unknown byte order %x", endian)
102 }
103
104 err = binary.Read(r, order, &geomType)
105 switch {
106 case err != nil:
107 return err
108 case geomType != wkbTriangleZ:
109 return fmt.Errorf("unknown geometry type %d", geomType)
110 }
111
112 var rings uint32
113 if err = binary.Read(r, order, &rings); err != nil {
114 return err
115 }
116 triangle := allocIndices()
117
118 for ring := uint32(0); ring < rings; ring++ {
119 var npoints uint32
120 if err = binary.Read(r, order, &npoints); err != nil {
121 return err
122 }
123
124 if npoints < 3 {
125 return errTooLessPoints
126 }
127
128 for p := uint32(0); p < npoints; p++ {
129 var x, y, z uint64
130 for _, addr := range []*uint64{&x, &y, &z} {
131 if err = binary.Read(r, order, addr); err != nil {
132 return err
133 }
134 }
135 if p >= 3 || ring >= 1 {
136 // Don't store the forth point.
137 continue
138 }
139 // Do this conversion later to spare reflect calls
140 // and allocs in binary.Read.
141 v.x = math.Float64frombits(x)
142 v.y = math.Float64frombits(y)
143 v.z = math.Float64frombits(z)
144 idx, found := v2i[v]
145 if !found {
146 idx = int32(len(vertices))
147 v2i[v] = idx
148 vertices = append(vertices, v)
149 min.minimize(v)
150 max.maximize(v)
151 }
152 triangle[p] = idx
153 }
154 }
155 triangles = append(triangles, triangle)
156 }
157
158 *t = tin{
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 (v *vertex) write(w io.Writer) error {
178 for _, addr := range []*float64{&v.x, &v.y, &v.z} {
179 if err := binary.Write(
180 w, binary.LittleEndian, math.Float64bits(*addr)); err != nil {
181 return err
182 }
183 }
184 return nil
185 }
186
187 func (t *tin) Serialize(w io.Writer) error {
188
189 if err := t.min.write(w); err != nil {
190 return err
191 }
192 if err := t.max.write(w); err != nil {
193 return err
194 }
195
196 if err := binary.Write(
197 w, binary.LittleEndian, uint32(len(t.vertices))); err != nil {
198 return err
199 }
200
201 for _, v := range t.vertices {
202 if err := v.write(w); err != nil {
203 return err
204 }
205 }
206 log.Printf("vertices %d (%d)\n", len(t.vertices), len(t.vertices)*3*8)
207
208 if err := binary.Write(
209 w, binary.LittleEndian, uint32(len(t.triangles))); err != nil {
210 return err
211 }
212
213 var buf [binary.MaxVarintLen32]byte
214 var written int
215 var last int32
216 for _, triangle := range t.triangles {
217 for _, idx := range triangle {
218 value := idx - last
219 n := binary.PutVarint(buf[:], int64(value))
220 for p := buf[:n]; len(p) > 0; p = p[n:] {
221 var err error
222 if n, err = w.Write(p); err != nil {
223 return err
224 }
225 written += n
226 }
227 last = idx
228 }
229 }
230 log.Printf("compressed tin indices in bytes: %d (%d)\n",
231 written, 3*4*len(t.triangles))
232
233 return nil
234 }