changeset 5706:148abae1fcd0 sr-v2

Quantize xyz in points in X/Y to 1/QuantScale.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 20 Feb 2024 12:52:09 +0100
parents 39d91e76c05c
children d5cafd49bed8
files pkg/imports/sr.go pkg/mesh/meshserialize_v2.go pkg/mesh/vertex.go
diffstat 3 files changed, 42 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/imports/sr.go	Tue Feb 20 09:51:20 2024 +0100
+++ b/pkg/imports/sr.go	Tue Feb 20 12:52:09 2024 +0100
@@ -512,9 +512,14 @@
 	if err := xyz.FromWKB(reproj); err != nil {
 		return nil, err
 	}
-
 	feedback.Info("Reprojecting points to EPSG %d took %v.",
 		epsg, time.Since(start))
+
+	start = time.Now()
+	xyz = xyz.QuantizeXY(mesh.QuantScale)
+	feedback.Info("Quantizing points in X/Y to 1/%d took %v.",
+		mesh.QuantScale, time.Since(start))
+
 	feedback.Info("Number of reprojected points: %d", len(xyz))
 	feedback.Info("Triangulate XYZ data.")
 
--- a/pkg/mesh/meshserialize_v2.go	Tue Feb 20 09:51:20 2024 +0100
+++ b/pkg/mesh/meshserialize_v2.go	Tue Feb 20 12:52:09 2024 +0100
@@ -24,10 +24,10 @@
 	"gemma.intevation.de/gemma/pkg/common"
 )
 
-const quantScale = 1_000
+const QuantScale = 1_000
 
-func quant(x float64) int64   { return int64(math.Round(x * quantScale)) }
-func unquant(x int64) float64 { return float64(x) / quantScale }
+func quant(x float64) int64   { return int64(math.Round(x * QuantScale)) }
+func unquant(x int64) float64 { return float64(x) / QuantScale }
 
 func (s *STRTree) serializeV2(w io.Writer) error {
 	return serializer(w, s,
--- a/pkg/mesh/vertex.go	Tue Feb 20 09:51:20 2024 +0100
+++ b/pkg/mesh/vertex.go	Tue Feb 20 12:52:09 2024 +0100
@@ -1161,6 +1161,39 @@
 	return out
 }
 
+// QuantizeXY quantize the X/Y values to scale and
+// removes duplicates in place. The z value of
+// duplicates will be averaged pairwise.
+func (mpz MultiPointZ) QuantizeXY(scale float64) MultiPointZ {
+	type qpoint struct {
+		x int64
+		y int64
+	}
+	m := make(map[qpoint]float64, len(mpz))
+	for _, p := range mpz {
+		k := qpoint{
+			x: int64(math.Round(p.X * scale)),
+			y: int64(math.Round(p.Y * scale)),
+		}
+		if z, ok := m[k]; ok {
+			m[k] = (z + p.Z) * 0.5
+		} else {
+			m[k] = p.Z
+		}
+	}
+	i := 0
+	invScale := 1 / scale
+	for k, z := range m {
+		mpz[i] = Vertex{
+			X: float64(k.x) * invScale,
+			Y: float64(k.y) * invScale,
+			Z: z,
+		}
+		i++
+	}
+	return mpz[:i]
+}
+
 // Filter returns a copy removed the vertices which
 // don't pass the filter test.
 func (mpz MultiPointZ) Filter(filter func(Vertex) bool) MultiPointZ {