view pkg/mesh/meshserialize_v1.go @ 5677:a57be8bfb6ea sr-v2

More suited file names.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sun, 11 Feb 2024 09:51:21 +0100
parents pkg/mesh/serialize_v1.go@d56e043bbbca
children 8ff842858434
line wrap: on
line source

// 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 mesh

import (
	"bufio"
	"encoding/binary"
	"io"
	"math"

	"gemma.intevation.de/gemma/pkg/log"
)

func (s *STRTree) serializeV1(w io.Writer) error {
	if err := s.tin.serializeV1(w); err != nil {
		return err
	}

	if err := binary.Write(w, binary.LittleEndian, uint8(s.Entries)); err != nil {
		return err
	}

	if err := s.serializeIndexV1(w); err != nil {
		return err
	}

	if err := s.serializeBBoxesV1(w); err != nil {
		return err
	}

	return nil
}

func (s *STRTree) serializeBBoxesV1(w io.Writer) 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) serializeIndexV1(w io.Writer) error {

	if err := binary.Write(w, binary.LittleEndian, int32(len(s.index))); err != nil {
		return err
	}

	var buf [binary.MaxVarintLen32]byte

	var last int32
	var written int

	for _, x := range s.index {
		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.Infof("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 (t *Tin) serializeV1(w io.Writer) error {

	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 := binary.Write(
		w, binary.LittleEndian, uint32(len(t.Vertices))); err != nil {
		return err
	}

	var err error
	vwrite := func(v float64) {
		if err == nil {
			err = binary.Write(w, binary.LittleEndian, math.Float64bits(v))
		}
	}

	for _, v := range t.Vertices {
		vwrite(v.X)
		vwrite(v.Y)
		vwrite(v.Z)
	}

	if err != nil {
		return err
	}
	log.Infof("vertices %d (%d)\n", len(t.Vertices), len(t.Vertices)*3*8)

	if err := binary.Write(
		w, binary.LittleEndian, uint32(len(t.Triangles))); err != nil {
		return err
	}

	var buf [binary.MaxVarintLen32]byte
	var written int
	var last int32
	for _, triangle := range t.Triangles {
		for _, idx := range triangle {
			value := idx - last
			n := binary.PutVarint(buf[:], int64(value))
			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 = idx
		}
	}
	log.Infof("compressed tin indices in bytes: %d (%d)\n",
		written, 3*4*len(t.Triangles))

	return nil
}

func (s *STRTree) deserializeBBoxesV1(r *bufio.Reader) error {

	var numBBoxes int32
	if err := binary.Read(r, binary.LittleEndian, &numBBoxes); err != nil {
		return err
	}

	bboxes := make([]Box2D, numBBoxes)
	s.bboxes = bboxes

	var err error

	read := func(v *float64) {
		if err == nil {
			err = binary.Read(r, binary.LittleEndian, v)
		}
	}

	for i := range bboxes {
		read(&bboxes[i].X1)
		read(&bboxes[i].Y1)
		read(&bboxes[i].X2)
		read(&bboxes[i].Y2)
	}

	return err
}

func (s *STRTree) deserializeIndexV1(r *bufio.Reader) error {
	var numIndex int32
	if err := binary.Read(r, binary.LittleEndian, &numIndex); err != nil {
		return err
	}
	index := make([]int32, numIndex)
	s.index = index

	var last int32
	for i := range index {
		v, err := binary.ReadVarint(r)
		if err != nil {
			return err
		}
		value := int32(v) + last
		index[i] = value
		last = value
	}

	return nil
}

func (s *STRTree) deserializeV1(r *bufio.Reader) error {
	s.tin = new(Tin)
	if err := s.tin.deserializeV1(r); err != nil {
		return err
	}
	var numEntries uint8
	if err := binary.Read(r, binary.LittleEndian, &numEntries); err != nil {
		return err
	}
	s.Entries = int(numEntries)

	if err := s.deserializeIndexV1(r); err != nil {
		return err
	}

	return s.deserializeBBoxesV1(r)
}

// deserializeV1 restores a TIN from a binary representation.
func (t *Tin) deserializeV1(r *bufio.Reader) error {

	if err := binary.Read(r, binary.LittleEndian, &t.EPSG); err != nil {
		return err
	}

	log.Infof("EPSG: %d\n", t.EPSG)

	if err := t.Min.Read(r); err != nil {
		return err
	}

	if err := t.Max.Read(r); err != nil {
		return err
	}

	log.Infof("BBOX: [[%f, %f, %f], [%f, %f, %f]]\n",
		t.Min.X, t.Min.Y, t.Min.Z,
		t.Max.X, t.Max.Y, t.Max.Z)

	var numVertices uint32
	if err := binary.Read(r, binary.LittleEndian, &numVertices); err != nil {
		return err
	}

	log.Infof("vertices: %d\n", numVertices)

	vertices := make([]Vertex, numVertices)
	t.Vertices = vertices

	for i := range vertices {
		if err := vertices[i].Read(r); err != nil {
			return err
		}
	}

	var numTriangles uint32
	if err := binary.Read(r, binary.LittleEndian, &numTriangles); err != nil {
		return err
	}

	log.Infof("triangles: %d\n", numTriangles)

	indices := make([]int32, 3*numTriangles)
	triangles := make([][]int32, numTriangles)
	t.Triangles = triangles

	var last int32

	for i := range triangles {
		tri := indices[:3]
		indices = indices[3:]
		triangles[i] = tri
		for j := range tri {
			v, err := binary.ReadVarint(r)
			if err != nil {
				return err
			}
			value := int32(v) + last
			tri[j] = value
			last = value
		}
	}

	return nil
}