view pkg/mesh/loader.go @ 5674:e54635c20d43 sr-v2

Load version fom database.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sat, 10 Feb 2024 17:03:58 +0100
parents 1222b777f51f
children d56e043bbbca
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) 2018 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"
	"bytes"
	"compress/gzip"
	"encoding/binary"
	"errors"
	"fmt"

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

const magicHeader = "SR3D"

func (s *STRTree) deserializeIndex(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) deserializeBBoxes(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) deserialize(r *bufio.Reader, version *int64) error {

	header, err := r.Peek(8)
	if err != nil {
		return err
	}

	if bytes.HasPrefix(header, []byte(magicHeader)) {
		realVersion := int64(binary.LittleEndian.Uint32(header[4:]))
		if version != nil && realVersion != *version {
			return fmt.Errorf("sounding result version mismatch: Have %d expect %d",
				realVersion, *version)
		}
		return s.deserializeVn(r, realVersion)
	}

	return s.deserializeV1(r)
}

func (s *STRTree) deserializeVn(r *bufio.Reader, version int64) error {
	if version == 1 {
		return s.deserializeV1(r)
	}
	// TODO: Implement me!
	return errors.New("not implemented, yet")
}

func (s *STRTree) deserializeV1(r *bufio.Reader) error {
	s.tin = new(Tin)
	if err := s.tin.Deserialize(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.deserializeIndex(r); err != nil {
		return err
	}

	return s.deserializeBBoxes(r)
}

// FromBytes restores a STRTree from a binary representation.
func (s *STRTree) FromBytes(data []byte, version *int64) error {
	r, err := gzip.NewReader(bytes.NewReader(data))
	if err != nil {
		return err
	}
	return s.deserialize(bufio.NewReader(r), version)
}

// Deserialize restores a TIN from a binary representation.
func (t *Tin) Deserialize(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
}