comparison pkg/mesh/tin.go @ 4827:f4abfd0ee8ad remove-octree-debris

Renamed octree package to mesh as there is no octree any more.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 05 Nov 2019 14:30:22 +0100
parents pkg/octree/tin.go@f5492fda097c
children 4847ac70103a
comparison
equal deleted inserted replaced
4826:ec5afada70ec 4827:f4abfd0ee8ad
1 // This is Free Software under GNU Affero General Public License v >= 3.0
2 // without warranty, see README.md and license for details.
3 //
4 // SPDX-License-Identifier: AGPL-3.0-or-later
5 // License-Filename: LICENSES/AGPL-3.0.txt
6 //
7 // Copyright (C) 2018 by via donau
8 // – Österreichische Wasserstraßen-Gesellschaft mbH
9 // Software engineering by Intevation GmbH
10 //
11 // Author(s):
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de>
13
14 package mesh
15
16 import (
17 "bytes"
18 "encoding/binary"
19 "errors"
20 "fmt"
21 "io"
22 "log"
23 "math"
24
25 "gemma.intevation.de/gemma/pkg/models"
26 "gemma.intevation.de/gemma/pkg/wkb"
27 )
28
29 var (
30 errNoByteSlice = errors.New("Not a byte slice")
31 errTooLessPoints = errors.New("Too less points")
32 )
33
34 // Tin stores a mesh of triangles with common vertices.
35 type Tin struct {
36 // EPSG holds the projection.
37 EPSG uint32
38 // Vertices are the shared vertices.
39 Vertices []Vertex
40 // Triangles are the triangles.
41 Triangles [][]int32
42
43 // Min is the lower left corner of the bbox.
44 Min Vertex
45 // Max is the upper right corner of the bbox.
46 Max Vertex
47 }
48
49 func (t *Tin) Clip(polygon *Polygon) map[int32]struct{} {
50 var tree STRTree
51 tree.Build(t)
52 return tree.Clip(polygon)
53 }
54
55 // FromWKB constructs the TIN from a WKB representation.
56 // Shared vertices are identified and referenced by the
57 // same index.
58 func (t *Tin) FromWKB(data []byte) error {
59 log.Printf("info: data length %d\n", len(data))
60
61 r := bytes.NewReader(data)
62
63 endian, err := r.ReadByte()
64
65 var order binary.ByteOrder
66
67 switch {
68 case err != nil:
69 return err
70 case endian == wkb.NDR:
71 order = binary.LittleEndian
72 case endian == wkb.XDR:
73 order = binary.BigEndian
74 default:
75 return fmt.Errorf("unknown byte order %x", endian)
76 }
77
78 var geomType uint32
79 err = binary.Read(r, order, &geomType)
80
81 switch {
82 case err != nil:
83 return err
84 case geomType != wkb.TinZ:
85 return fmt.Errorf("unknown geometry type %x", geomType)
86 }
87
88 var num uint32
89 if err = binary.Read(r, order, &num); err != nil {
90 return err
91 }
92
93 vertices := make([]Vertex, 0, 100000)
94
95 var v Vertex
96
97 v2i := make(map[Vertex]int32, 100000)
98
99 var indexPool []int32
100
101 allocIndices := func() []int32 {
102 if len(indexPool) == 0 {
103 indexPool = make([]int32, 3*8*1024)
104 }
105 ids := indexPool[:3]
106 indexPool = indexPool[3:]
107 return ids
108 }
109
110 var triangles [][]int32
111
112 min := Vertex{math.MaxFloat64, math.MaxFloat64, math.MaxFloat64}
113 max := Vertex{-math.MaxFloat64, -math.MaxFloat64, -math.MaxFloat64}
114
115 for i := uint32(0); i < num; i++ {
116
117 endian, err = r.ReadByte()
118 switch {
119 case err != nil:
120 return err
121 case endian == wkb.NDR:
122 order = binary.LittleEndian
123 case endian == wkb.XDR:
124 order = binary.BigEndian
125 default:
126 return fmt.Errorf("unknown byte order %x", endian)
127 }
128
129 err = binary.Read(r, order, &geomType)
130 switch {
131 case err != nil:
132 return err
133 case geomType != wkb.TriangleZ:
134 return fmt.Errorf("unknown geometry type %d", geomType)
135 }
136
137 var rings uint32
138 if err = binary.Read(r, order, &rings); err != nil {
139 return err
140 }
141 triangle := allocIndices()
142
143 for ring := uint32(0); ring < rings; ring++ {
144 var npoints uint32
145 if err = binary.Read(r, order, &npoints); err != nil {
146 return err
147 }
148
149 if npoints < 3 {
150 return errTooLessPoints
151 }
152
153 for p := uint32(0); p < npoints; p++ {
154 var x, y, z uint64
155 for _, addr := range []*uint64{&x, &y, &z} {
156 if err = binary.Read(r, order, addr); err != nil {
157 return err
158 }
159 }
160 if p >= 3 || ring >= 1 {
161 // Don't store the forth point.
162 continue
163 }
164 // Do this conversion later to spare reflect calls
165 // and allocs in binary.Read.
166 v.X = math.Float64frombits(x)
167 v.Y = math.Float64frombits(y)
168 v.Z = math.Float64frombits(z)
169 idx, found := v2i[v]
170 if !found {
171 idx = int32(len(vertices))
172 v2i[v] = idx
173 vertices = append(vertices, v)
174 min.Minimize(v)
175 max.Maximize(v)
176 }
177 triangle[p] = idx
178 }
179 }
180 triangles = append(triangles, triangle)
181 }
182
183 log.Printf("info: bbox: [[%f, %f], [%f, %f]]\n",
184 min.X, min.Y, max.X, max.Y)
185
186 *t = Tin{
187 EPSG: models.WGS84,
188 Vertices: vertices,
189 Triangles: triangles,
190 Min: min,
191 Max: max,
192 }
193
194 return nil
195 }
196
197 // Scan implements the sql.Scanner interface.
198 func (t *Tin) Scan(raw interface{}) error {
199 if raw == nil {
200 return nil
201 }
202 data, ok := raw.([]byte)
203 if !ok {
204 return errNoByteSlice
205 }
206 return t.FromWKB(data)
207 }
208
209 func (t *Tin) serialize(w io.Writer) error {
210
211 if err := binary.Write(w, binary.LittleEndian, t.EPSG); err != nil {
212 return err
213 }
214
215 if err := t.Min.Write(w); err != nil {
216 return err
217 }
218 if err := t.Max.Write(w); err != nil {
219 return err
220 }
221
222 if err := binary.Write(
223 w, binary.LittleEndian, uint32(len(t.Vertices))); err != nil {
224 return err
225 }
226
227 var err error
228 vwrite := func(v float64) {
229 if err == nil {
230 err = binary.Write(w, binary.LittleEndian, math.Float64bits(v))
231 }
232 }
233
234 for _, v := range t.Vertices {
235 vwrite(v.X)
236 vwrite(v.Y)
237 vwrite(v.Z)
238 }
239
240 if err != nil {
241 return err
242 }
243 log.Printf("info: vertices %d (%d)\n", len(t.Vertices), len(t.Vertices)*3*8)
244
245 if err := binary.Write(
246 w, binary.LittleEndian, uint32(len(t.Triangles))); err != nil {
247 return err
248 }
249
250 var buf [binary.MaxVarintLen32]byte
251 var written int
252 var last int32
253 for _, triangle := range t.Triangles {
254 for _, idx := range triangle {
255 value := idx - last
256 n := binary.PutVarint(buf[:], int64(value))
257 for p := buf[:n]; len(p) > 0; p = p[n:] {
258 var err error
259 if n, err = w.Write(p); err != nil {
260 return err
261 }
262 written += n
263 }
264 last = idx
265 }
266 }
267 log.Printf("info: compressed tin indices in bytes: %d (%d)\n",
268 written, 3*4*len(t.Triangles))
269
270 return nil
271 }