diff pkg/octree/strtree.go @ 4646:89a72e0e2f9b stree-experiment

Add a method to serialize an STRTree.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sun, 13 Oct 2019 15:45:39 +0200
parents a1a9b1eab57c
children 18331577a251
line wrap: on
line diff
--- a/pkg/octree/strtree.go	Fri Oct 11 23:46:35 2019 +0200
+++ b/pkg/octree/strtree.go	Sun Oct 13 15:45:39 2019 +0200
@@ -14,8 +14,14 @@
 package octree
 
 import (
+	"bytes"
+	"encoding/binary"
+	"io"
+	"log"
 	"math"
 	"sort"
+
+	"github.com/pierrec/lz4"
 )
 
 const STRTreeDefaultEntries = 8
@@ -44,6 +50,9 @@
 			}
 		} else { // leaf
 			top = -top - 1
+			if !s.bbox(top).Contains(x, y) {
+				continue
+			}
 			for i, n := int32(0), s.index[top+1]; i < n; i++ {
 				idx := s.index[top+2+i]
 				ti := s.tin.Triangles[idx]
@@ -150,6 +159,95 @@
 	return removed
 }
 
+func (s *STRTree) serializeIndex(w io.Writer) error {
+
+	if err := binary.Write(w, binary.LittleEndian, int32(len(s.index))); err != nil {
+		return err
+	}
+
+	if err := binary.Write(w, binary.LittleEndian, s.index[0]); err != nil {
+		return err
+	}
+
+	var buf [binary.MaxVarintLen32]byte
+
+	var last int32
+	var written int
+
+	for _, x := range s.index[1:] {
+		delta := x - last
+		n := binary.PutVarint(buf[:], int64(delta))
+		for p := buf[:n]; len(p) > 0; p = p[n:] {
+			var err error
+			if n, err = w.Write(p); err != nil {
+				return err
+			}
+			written += n
+		}
+
+		last = x
+	}
+	log.Printf("info: compressed index in bytes: %d %.2f (%d %.2f)\n",
+		written,
+		float64(written)/(1024*1024),
+		4*len(s.index),
+		float64(4*len(s.index))/(1024*1024),
+	)
+
+	return nil
+}
+
+func (s *STRTree) serializeBBoxes(w io.Writer) (rr error) {
+
+	if err := binary.Write(w, binary.LittleEndian, int32(len(s.bboxes))); err != nil {
+		return err
+	}
+
+	var err error
+
+	write := func(v float64) {
+		if err == nil {
+			err = binary.Write(w, binary.LittleEndian, math.Float64bits(v))
+		}
+	}
+	for _, box := range s.bboxes {
+		write(box.X1)
+		write(box.Y1)
+		write(box.X2)
+		write(box.Y2)
+	}
+
+	return err
+}
+
+func (s *STRTree) Bytes() ([]byte, error) {
+
+	var buf bytes.Buffer
+	w := lz4.NewWriter(&buf)
+
+	if err := s.tin.serialize(w); err != nil {
+		return nil, err
+	}
+
+	if err := binary.Write(w, binary.LittleEndian, uint8(s.Entries)); err != nil {
+		return nil, err
+	}
+
+	if err := s.serializeIndex(w); err != nil {
+		return nil, err
+	}
+
+	if err := s.serializeBBoxes(w); err != nil {
+		return nil, err
+	}
+
+	if err := w.Flush(); err != nil {
+		return nil, err
+	}
+
+	return buf.Bytes(), nil
+}
+
 func (s *STRTree) allTriangles(pos int32, tris map[int32]struct{}) {
 	stack := []int32{pos}
 	for len(stack) > 0 {