changeset 5688:6281c18b109f sr-v2

Finsh serializing v2 meshes.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 12 Feb 2024 02:27:41 +0100
parents 8ff842858434
children 159291854063
files pkg/common/delta.go pkg/mesh/meshserialize_v2.go
diffstat 2 files changed, 144 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg/common/delta.go	Mon Feb 12 02:27:41 2024 +0100
@@ -0,0 +1,32 @@
+// This is Free Software under GNU Affero General Public License v >= 3.0
+// without warranty, see README.md and license for details.
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// License-Filename: LICENSES/AGPL-3.0.txt
+//
+// Copyright (C) 2024 by via donau
+//   – Österreichische Wasserstraßen-Gesellschaft mbH
+// Software engineering by Intevation GmbH
+//
+// Author(s):
+//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
+
+package common
+
+// Delta returns a function which returns its argument when called
+// the first time and the delta to the last call afterwards.
+func Delta() func(int64) int64 {
+	var last int64
+	first := true
+	return func(x int64) (y int64) {
+		if first {
+			first = false
+			y = x
+			last = x
+		} else {
+			y = x - last
+			last = x
+		}
+		return
+	}
+}
--- a/pkg/mesh/meshserialize_v2.go	Mon Feb 12 01:31:48 2024 +0100
+++ b/pkg/mesh/meshserialize_v2.go	Mon Feb 12 02:27:41 2024 +0100
@@ -22,8 +22,14 @@
 	"math"
 	"slices"
 	"sort"
+
+	"gemma.intevation.de/gemma/pkg/common"
 )
 
+const quantScale = 1_000
+
+func quant(x float64) int64 { return int64(math.Round(x * quantScale)) }
+
 func (s *STRTree) serializeV2(w io.Writer) error {
 	// Write header
 	if _, err := w.Write([]byte(magicHeader)); err != nil {
@@ -47,18 +53,118 @@
 }
 
 func (t *Tin) serializeV2(w io.Writer) error {
-	// TODO: Implement me!
-	return errors.New("not implemented, yet")
+	if err := binary.Write(w, binary.LittleEndian, t.EPSG); err != nil {
+		return err
+	}
+	if err := t.Min.Write(w); err != nil {
+		return err
+	}
+	if err := t.Max.Write(w); err != nil {
+		return err
+	}
+	if err := t.serializeVerticesV2(w); err != nil {
+		return err
+	}
+	return t.serializeTrianglesV2(w)
+}
+
+func zigZag(buf []byte, w io.Writer, x int64) error {
+	for b := buf[:binary.PutVarint(buf, x)]; len(b) > 0; {
+		m, err := w.Write(buf)
+		if err != nil {
+			return err
+		}
+		b = b[m:]
+	}
+	return nil
+}
+
+func (t *Tin) serializeVerticesV2(w io.Writer) error {
+	vertices := t.Vertices
+	if err := binary.Write(w, binary.LittleEndian, uint32(len(vertices))); err != nil {
+		return err
+	}
+	m := t.Min
+	buf := make([]byte, binary.MaxVarintLen64)
+	for dim := range 3 {
+		delta := common.Delta()
+		for i := range vertices {
+			var v float64
+			switch dim {
+			case 0:
+				v = vertices[i].X - m.X
+			case 1:
+				v = vertices[i].Y - m.Y
+			case 2:
+				v = vertices[i].Z - m.Z
+			}
+			q := quant(v)
+			d := delta(q)
+			if err := zigZag(buf, w, d); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func (t *Tin) serializeTrianglesV2(w io.Writer) error {
+	triangles := t.Triangles
+	if err := binary.Write(w, binary.LittleEndian, uint32(len(triangles))); err != nil {
+		return err
+	}
+	buf := make([]byte, binary.MaxVarintLen64)
+	delta := common.Delta()
+	for _, tri := range triangles {
+		for _, idx := range tri {
+			d := delta(int64(idx))
+			if err := zigZag(buf, w, d); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
 }
 
 func (s *STRTree) serializeIndexV2(w io.Writer) error {
-	// TODO: Implement me!
-	return errors.New("not implemented, yet")
+	index := s.index
+	if err := binary.Write(w, binary.LittleEndian, uint32(len(index))); err != nil {
+		return err
+	}
+	buf := make([]byte, binary.MaxVarintLen64)
+	delta := common.Delta()
+	for _, idx := range index {
+		d := delta(int64(idx))
+		if err := zigZag(buf, w, d); err != nil {
+			return err
+		}
+	}
+	return nil
 }
 
 func (s *STRTree) serializeBBoxesV2(w io.Writer) error {
-	// TODO: Implement me!
-	return errors.New("not implemented, yet")
+	boxes := s.bboxes
+	if err := binary.Write(w, binary.LittleEndian, uint32(len(boxes))); err != nil {
+		return err
+	}
+	var (
+		m      = s.Min()
+		x1     = func(b Box2D) int64 { return quant(b.X1 - m.X) }
+		y1     = func(b Box2D) int64 { return quant(b.Y1 - m.Y) }
+		width  = func(b Box2D) int64 { return quant(b.X2 - b.X1) }
+		height = func(b Box2D) int64 { return quant(b.Y2 - b.Y1) }
+		buf    = make([]byte, binary.MaxVarintLen64)
+	)
+	for _, proj := range []func(Box2D) int64{x1, y1, width, height} {
+		delta := common.Delta()
+		for _, b := range boxes {
+			v := delta(proj(b))
+			if err := zigZag(buf, w, v); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
 }
 
 func (s *STRTree) deserializeV2(r *bufio.Reader) error {