diff pkg/octree/vertex.go @ 727:41c8dc61f38f

Moved octree loading stuff to octree package.
author Sascha L. Teichmann <teichmann@intevation.de>
date Sat, 22 Sep 2018 21:57:30 +0200
parents cmd/octree2contour/vertex.go@5af9ab39e715
children b0bd242ff821
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg/octree/vertex.go	Sat Sep 22 21:57:30 2018 +0200
@@ -0,0 +1,195 @@
+package octree
+
+import (
+	"bytes"
+	"encoding/binary"
+	"io"
+	"math"
+)
+
+type (
+	Vertex struct {
+		X float64
+		Y float64
+		Z float64
+	}
+
+	Triangle [3]Vertex
+
+	Line [2]Vertex
+
+	LineStringZ      []Vertex
+	MultiLineStringZ []LineStringZ
+)
+
+const (
+	wkbNDR              byte   = 1
+	wkbPointZ           uint32 = 1000 + 1
+	wkbLineStringZ      uint32 = 1000 + 2
+	wkbMultiLineStringZ uint32 = 1000 + 5
+)
+
+func (v *Vertex) Minimize(w Vertex) {
+	if w.X < v.X {
+		v.X = w.X
+	}
+	if w.Y < v.Y {
+		v.Y = w.Y
+	}
+	if w.Z < v.Z {
+		v.Z = w.Z
+	}
+}
+
+func (v *Vertex) Maximize(w Vertex) {
+	if w.X > v.X {
+		v.X = w.X
+	}
+	if w.Y > v.Y {
+		v.Y = w.Y
+	}
+	if w.Z > v.Z {
+		v.Z = w.Z
+	}
+}
+
+func (v Vertex) Sub(w Vertex) Vertex {
+	return Vertex{
+		v.X - w.X,
+		v.Y - w.Y,
+		v.Z - w.Z,
+	}
+}
+
+func (v Vertex) Add(w Vertex) Vertex {
+	return Vertex{
+		v.X + w.X,
+		v.Y + w.Y,
+		v.Z + w.Z,
+	}
+}
+
+func (v Vertex) scale(s float64) Vertex {
+	return Vertex{
+		s * v.X,
+		s * v.Y,
+		s * v.Z,
+	}
+}
+
+func Interpolate(v1, v2 Vertex) func(Vertex) Vertex {
+	v2 = v2.Sub(v1)
+	return func(s Vertex) Vertex {
+		return Vertex{
+			v2.X*s.X + v1.X,
+			v2.Y*s.Y + v1.Y,
+			v2.Z*s.Z + v1.Z,
+		}
+	}
+}
+
+func (a Vertex) Less(b Vertex) bool {
+	return a.X < b.X || a.Y < b.Y || a.Z < b.Z
+}
+
+func NewLine(p1, p2 Vertex) Line {
+	return Line{
+		p2.Sub(p1),
+		p1,
+	}
+}
+
+func (l Line) Eval(t float64) Vertex {
+	return l[0].scale(t).Add(l[1])
+}
+
+func (l Line) IntersectHorizontal(h float64) Vertex {
+	t := (h - l[1].Z) / l[0].Z
+	return l.Eval(t)
+}
+
+func side(z, h float64) int {
+	switch {
+	case z < h:
+		return -1
+	case z > h:
+		return +1
+	}
+	return 0
+}
+
+func (t *Triangle) IntersectHorizontal(h float64) LineStringZ {
+	sides := [3]int{
+		side(t[0].Z, h),
+		side(t[1].Z, h),
+		side(t[2].Z, h),
+	}
+
+	var points LineStringZ
+
+	for i := 0; i < 3; i++ {
+		j := (i + 1) % 3
+		si := sides[i]
+		sj := sides[j]
+
+		switch {
+		case si == 0 && sj == 0:
+			// both on plane
+			points = append(points, t[i], t[j])
+		case si == 0 && sj != 0:
+			// first on plane
+			points = append(points, t[i])
+		case si != 0 && sj == 0:
+			// second on plane
+			points = append(points, t[j])
+		case si == sj:
+			// both on same side
+		default:
+			// real intersection
+			v := NewLine(t[i], t[j]).IntersectHorizontal(h)
+			points = append(points, v)
+		}
+	}
+
+	return points
+}
+
+func (v *Vertex) read(r io.Reader) error {
+	var buf [8]byte
+	b := buf[:]
+	if _, err := io.ReadFull(r, b); err != nil {
+		return nil
+	}
+	v.X = math.Float64frombits(binary.LittleEndian.Uint64(b))
+	if _, err := io.ReadFull(r, b); err != nil {
+		return nil
+	}
+	v.Y = math.Float64frombits(binary.LittleEndian.Uint64(b))
+	if _, err := io.ReadFull(r, b); err != nil {
+		return nil
+	}
+	v.Z = math.Float64frombits(binary.LittleEndian.Uint64(b))
+	return nil
+}
+
+func (mls MultiLineStringZ) AsWKB() []byte {
+
+	var buf bytes.Buffer
+
+	binary.Write(&buf, binary.LittleEndian, wkbNDR)
+	binary.Write(&buf, binary.LittleEndian, wkbMultiLineStringZ)
+	binary.Write(&buf, binary.LittleEndian, uint32(len(mls)))
+
+	for _, ml := range mls {
+		binary.Write(&buf, binary.LittleEndian, wkbNDR)
+		binary.Write(&buf, binary.LittleEndian, wkbLineStringZ)
+		binary.Write(&buf, binary.LittleEndian, uint32(len(ml)))
+		for _, p := range ml {
+			binary.Write(&buf, binary.LittleEndian, math.Float64bits(p.X))
+			binary.Write(&buf, binary.LittleEndian, math.Float64bits(p.Y))
+			binary.Write(&buf, binary.LittleEndian, math.Float64bits(p.Z))
+		}
+	}
+
+	return buf.Bytes()
+}