Mercurial > gemma
diff pkg/octree/strtree.go @ 4658:4bbfe3dd2ab5 stree-experiment
Completed usage of STRTrees.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 14 Oct 2019 14:58:04 +0200 |
parents | 3eda5a7215ab |
children | 6e179b338f1a |
line wrap: on
line diff
--- a/pkg/octree/strtree.go Mon Oct 14 13:18:15 2019 +0200 +++ b/pkg/octree/strtree.go Mon Oct 14 14:58:04 2019 +0200 @@ -32,12 +32,72 @@ bboxes []Box2D } +// Vertical does a vertical cross cut from (x1, y1) to (x2, y2). +func (s *STRTree) 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 < s.tin.Min.X || s.tin.Max.X < box.X1 || + box.Y2 < s.tin.Min.Y || s.tin.Max.Y < box.Y1 { + return + } + + line := NewPlane2D(x1, y1, x2, y2) + + vertices := s.tin.Vertices + + stack := []int32{s.index[0]} + + for len(stack) > 0 { + top := stack[len(stack)-1] + stack = stack[:len(stack)-1] + + if top > 0 { // node + if b := s.bbox(top); b.Intersects(box) && b.IntersectsPlane(line) { + n := s.index[top+1] + stack = append(stack, s.index[top+2:top+2+n]...) + } + } else { // leaf + top = -top - 1 + if b := s.bbox(top); !b.Intersects(box) || !b.IntersectsPlane(line) { + continue + } + n := s.index[top+1] + for _, idx := range s.index[top+2 : top+2+n] { + ti := s.tin.Triangles[idx] + t := Triangle{ + vertices[ti[0]], + vertices[ti[1]], + vertices[ti[2]], + } + v0 := line.Eval(t[0].X, t[0].Y) + v1 := line.Eval(t[1].X, t[1].Y) + v2 := line.Eval(t[2].X, t[2].Y) + + if onPlane(v0) || onPlane(v1) || onPlane(v2) || + sides(sides(sides(0, v0), v1), v2) == 3 { + fn(&t) + } + } + } + } +} + func (s *STRTree) Min() Vertex { return s.tin.Min } func (s *STRTree) Max() Vertex { return s.tin.Max } func (s *STRTree) EPSG() uint32 { return s.tin.EPSG } func (s *STRTree) Value(x, y float64) (float64, bool) { + if len(s.index) == 0 { + return 0, false + } + stack := []int32{s.index[0]} vertices := s.tin.Vertices @@ -56,8 +116,8 @@ if !s.bbox(top).Contains(x, y) { continue } - for i, n := int32(0), s.index[top+1]; i < n; i++ { - idx := s.index[top+2+i] + n := s.index[top+1] + for _, idx := range s.index[top+2 : top+2+n] { ti := s.tin.Triangles[idx] t := Triangle{ vertices[ti[0]], @@ -412,3 +472,51 @@ } return int32(-(pos + 1)) } + +func (s *STRTree) Diff(other *STRTree) PointMap { + + firstVs, secondVs := s.tin.Vertices, other.tin.Vertices + + result := make(PointMap, len(firstVs)+len(secondVs)) + + sliceWork( + firstVs, + result, + func(slice []Vertex, turn func([]Vertex) []Vertex) { + p := turn(nil) + for i := range slice { + v := &slice[i] + if z, found := other.Value(v.X, v.Y); found { + p = append(p, Vertex{v.X, v.Y, v.Z - z}) + if len(p) == cap(p) { + p = turn(p) + } + } + } + if len(p) > 0 { + turn(p) + } + }) + + sliceWork( + secondVs, + result, + func( + slice []Vertex, turn func([]Vertex) []Vertex) { + p := turn(nil) + for i := range slice { + v := &slice[i] + if z, found := s.Value(v.X, v.Y); found { + p = append(p, Vertex{v.X, v.Y, z - v.Z}) + if len(p) == cap(p) { + p = turn(p) + } + } + } + if len(p) > 0 { + turn(p) + } + }) + + return result +}