Mercurial > gemma
view pkg/mesh/meshserialize_v2.go @ 5684:536e842d9bfa sr-v2
Reorder vertices in tins to minimize delta distances.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 11 Feb 2024 22:32:55 +0100 |
parents | 33499bd1b829 |
children | 0ee8ace01b60 |
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 ( "cmp" "math" "slices" "sort" ) 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) } slices.SortFunc(indices, func(a, b int32) int { return cmp.Compare(vertices[a].X, vertices[b].X) }) n := int(math.Sqrt(float64(len(vertices)))) m := len(vertices) / n var ( up = func(a, b int32) int { return cmp.Compare(vertices[a].Y, vertices[b].Y) } down = func(a, b int32) int { return cmp.Compare(vertices[b].Y, vertices[a].Y) } ) for p := indices; len(p) > 0; up, down = down, up { l := min(len(p), m) slices.SortStableFunc(p[:l], down) 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] } } }