changeset 755:1a1a8b5f2d02

Vertical traversal of octree for cross sections. WIP.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 24 Sep 2018 18:41:29 +0200
parents 105c421f99b1
children 5e14000829d1
files pkg/controllers/octreecross.go pkg/octree/tree.go
diffstat 2 files changed, 108 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/octreecross.go	Mon Sep 24 17:30:55 2018 +0200
+++ b/pkg/controllers/octreecross.go	Mon Sep 24 18:41:29 2018 +0200
@@ -32,12 +32,11 @@
 
 	dst := make(models.GeoJSONLineCoordinates, len(src))
 	for i, s := range src {
-		d := &dst[i]
 		if err := stmt.QueryRowContext(
 			ctx,
 			s.Lat, s.Lon,
 			fromEPSG, toEPSG,
-		).Scan(&d.Lat, &d.Lon); err != nil {
+		).Scan(&dst[i].Lat, &dst[i].Lon); err != nil {
 			return nil, err
 		}
 	}
--- a/pkg/octree/tree.go	Mon Sep 24 17:30:55 2018 +0200
+++ b/pkg/octree/tree.go	Mon Sep 24 18:41:29 2018 +0200
@@ -15,18 +15,121 @@
 	Max Vertex
 }
 
+type box2d struct {
+	x1 float64
+	y1 float64
+	x2 float64
+	y2 float64
+}
+
+func (a box2d) intersects(b box2d) bool {
+	return !(a.x2 < a.x1 || a.x2 < b.x1 ||
+		a.y2 < a.y1 || a.y2 < b.y1)
+}
+
+func (a box2d) mid() (float64, float64) {
+	return (a.x2-a.x1)*0.5 + a.x1, (a.y2-a.y1)*0.5 + a.y1
+}
+
+func (a box2d) xi(i int) float64 {
+	if i == 0 {
+		return a.x1
+	}
+	return a.x2
+}
+
+func (a box2d) yi(i int) float64 {
+	if i == 0 {
+		return a.y1
+	}
+	return a.y2
+}
+
+var scale = [][]float64{
+	{0.0, 0.0, 0.5, 0.5},
+	{0.5, 0.0, 1.0, 0.5},
+	{0.0, 0.5, 0.5, 1.0},
+	{0.5, 0.5, 1.0, 1.0},
+}
+
+func (ot *Tree) Vertical(x1, y1, x2, y2 float64, fn func(*Triangle)) {
+
+	box := box2d{
+		x1: math.Min(x1, x2),
+		y1: math.Min(y1, y2),
+		x2: math.Max(x1, x2),
+		y2: math.Max(y1, y2),
+	}
+
+	// out of bounding box
+	if box.x2 < ot.Min.X || ot.Max.X < box.x1 ||
+		box.y2 < ot.Min.Y || ot.Max.Y < box.y1 {
+		return
+	}
+
+	type frame struct {
+		pos int32
+		box2d
+	}
+
+	stack := []frame{{1, box2d{ot.Min.X, ot.Min.Y, ot.Max.X, ot.Max.Y}}}
+
+	for len(stack) > 0 {
+		top := stack[len(stack)-1]
+		stack = stack[:len(stack)-1]
+
+		if top.pos > 0 { // node
+			midx, midy := top.mid()
+
+			var all uint
+			for i := 0; i < 2; i++ {
+				for j := 0; j < 2; j++ {
+					x, y := box.xi(i), box.yi(j)
+					var code uint
+					if x > midx {
+						code |= 1
+					}
+					if y > midy {
+						code |= 2
+					}
+					all |= 1 << code
+				}
+			}
+
+			dx := top.x2 - top.x1
+			dy := top.y2 - top.y1
+			for i := 0; all != 0; i++ {
+				if all&1 == 1 {
+					s := scale[i]
+					nbox := box2d{
+						dx*s[0] + top.x1,
+						dy*s[1] + top.y1,
+						dx*s[2] + top.x1,
+						dy*s[3] + top.y1,
+					}
+					// TODO: Push two frames to stack.
+					_ = nbox
+				}
+				all >>= 1
+			}
+
+		} else { // leaf
+		}
+	}
+}
+
 func (ot *Tree) Horizontal(h float64, fn func(*Triangle)) {
 
+	if h < ot.Min.Z || ot.Max.Z < h {
+		return
+	}
+
 	type frame struct {
 		pos int32
 		min float64
 		max float64
 	}
 
-	if h < ot.Min.Z || ot.Max.Z < h {
-		return
-	}
-
 	stack := []frame{{1, ot.Min.Z, ot.Max.Z}}
 
 	dupes := map[int32]struct{}{}