Mercurial > gemma
view pkg/mesh/meshserialize_v2.go @ 5686:c33a5354328d sr-v2
Add stubs for de/serialize v2 meshes.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 12 Feb 2024 01:17:22 +0100 |
parents | 0ee8ace01b60 |
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" "cmp" "errors" "io" "math" "slices" "sort" ) func (s *STRTree) serializeV2(w io.Writer) error { // TODO: implement me! return errors.New("not implemented, yet") } func (s *STRTree) deserializeV2(r *bufio.Reader) error { // TODO: implement me! return errors.New("not implemented, yet") } // optimizeForSerializationV2 prepares the mesh to be stored in V2. func (s *STRTree) optimizeForSerializationV2() { s.removeUnusedTriangles() s.sortVertices() s.sortIndices() } // removeUnusedTriangles removes all triangles from the // TIN that are not registered in the spatial index. func (s *STRTree) removeUnusedTriangles() { used := make([]bool, len(s.tin.Triangles)) unused := len(used) s.allTriangleIndices(func(indices []int32) { for _, idx := range indices { used[idx] = true unused-- // They only occur once in the spatial index. } }) if unused <= 0 { return } newTris := make([][]int32, 0, len(s.tin.Triangles)-unused) remap := map[int32]int32{} for idx, tri := range s.tin.Triangles { if used[idx] { remap[int32(idx)] = int32(len(newTris)) newTris = append(newTris, tri) } } s.tin.Triangles = newTris // Update the spatial index as the gaps are now closed. s.allTriangleIndices(func(indices []int32) { for i, idx := range indices { indices[i] = remap[idx] } }) } // sortVertices so that the deltas between neighbors are minimized. func (s *STRTree) sortVertices() { vertices := s.tin.Vertices indices := make([]int32, len(vertices)) for i := range len(indices) { indices[i] = int32(i) } // Take aspect ratio of bbox into account. width := s.tin.Max.X - s.tin.Min.X height := s.tin.Max.Y - s.tin.Min.Y if width == 0 || height == 0 { return } // v = len(vertices) // r = max(w, h)/min(w, h) // n * t = v <=> n = v/t // n / t = r <=> n = r*t // v/t = r*t // v = r*t^2 // v/r = t^2 // t = sqrt(v/r) r := float64(max(width, height)) / float64(min(width, height)) t := int(math.Ceil(math.Sqrt(float64(len(vertices)) / r))) var d1, d2 func(int32, int32) int if width > height { // Sort in X first and slices alternating up and down slices.SortFunc(indices, func(a, b int32) int { return cmp.Compare(vertices[a].X, vertices[b].X) }) d1 = func(a, b int32) int { return cmp.Compare(vertices[a].Y, vertices[b].Y) } d2 = func(a, b int32) int { return cmp.Compare(vertices[b].Y, vertices[a].Y) } } else { // Sort in Y first and slices alternating left and right slices.SortFunc(indices, func(a, b int32) int { return cmp.Compare(vertices[a].Y, vertices[b].Y) }) d1 = func(a, b int32) int { return cmp.Compare(vertices[a].X, vertices[b].X) } d2 = func(a, b int32) int { return cmp.Compare(vertices[b].X, vertices[a].X) } } for p := indices; len(p) > 0; d1, d2 = d2, d1 { l := min(len(p), t) slices.SortStableFunc(p[:l], d2) p = p[l:] } // We really need to to sort the vertices actually, too. sort.Slice(vertices, func(i, j int) bool { return indices[i] < indices[j] }) reindices := make([]int32, len(indices)) for i, idx := range indices { reindices[idx] = int32(i) } // Update the indices in the triangles. for _, tri := range s.tin.Triangles { for i, idx := range tri { tri[i] = reindices[idx] } } }