Mercurial > gemma
changeset 1692:f4dcbe8941a1
Octree: Resolved the remaing golint issues with this package.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 31 Dec 2018 11:13:49 +0100 |
parents | de09bd3b5c05 |
children | cdc8933949f2 |
files | pkg/octree/cache.go pkg/octree/contours.go pkg/octree/loader.go pkg/octree/tin.go pkg/octree/tree.go pkg/octree/vertex.go |
diffstat | 6 files changed, 99 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/octree/cache.go Sun Dec 30 16:24:51 2018 +0100 +++ b/pkg/octree/cache.go Mon Dec 31 11:13:49 2018 +0100 @@ -31,6 +31,9 @@ tree *Tree access time.Time } + + // Cache holds Octrees for a defined amount of time in memory + // before they are released. Cache struct { sync.Mutex entries map[cacheKey]*cacheEntry @@ -87,6 +90,7 @@ } } +// FromCache fetches an Octree from the global Octree cache. func FromCache( ctx context.Context, conn *sql.Conn, @@ -135,7 +139,7 @@ } } - tree, err := Deserialize(data) + tree, err := deserialize(data) if err != nil { return nil, err }
--- a/pkg/octree/contours.go Sun Dec 30 16:24:51 2018 +0100 +++ b/pkg/octree/contours.go Mon Dec 31 11:13:49 2018 +0100 @@ -19,6 +19,8 @@ "sync" ) +// ContourResult stores an calculated iso line for a given height. +// Is used as a future variable in the concurrent iso line calculation. type ContourResult struct { Height float64 Lines MultiLineStringZ @@ -28,6 +30,8 @@ cond *sync.Cond } +// NewContourResult prepares a future variable to later hold +// the result of the iso line calculation. func NewContourResult(height float64) *ContourResult { cr := ContourResult{Height: height} cr.cond = sync.NewCond(&cr.mu) @@ -56,6 +60,10 @@ cr.cond.Signal() } +// DoContours calculates the iso line for the given heights. +// This is done concurrently. +// It is guaranteed that the results are given to the store +// function in order of the original heights values. func DoContours(tree *Tree, heights []float64, store func(*ContourResult)) { contours := make([]*ContourResult, len(heights))
--- a/pkg/octree/loader.go Sun Dec 30 16:24:51 2018 +0100 +++ b/pkg/octree/loader.go Mon Dec 31 11:13:49 2018 +0100 @@ -18,7 +18,6 @@ "bytes" "encoding/binary" "log" - "os" "github.com/golang/snappy" ) @@ -112,19 +111,7 @@ return tree, nil } -func LoadTree(fname string) (*Tree, error) { - - f, err := os.Open(fname) - if err != nil { - return nil, err - } - defer f.Close() - return loadReader( - bufio.NewReader( - snappy.NewReader(f))) -} - -func Deserialize(data []byte) (*Tree, error) { +func deserialize(data []byte) (*Tree, error) { return loadReader( bufio.NewReader( snappy.NewReader(
--- a/pkg/octree/tin.go Sun Dec 30 16:24:51 2018 +0100 +++ b/pkg/octree/tin.go Mon Dec 31 11:13:49 2018 +0100 @@ -32,15 +32,24 @@ errTooLessPoints = errors.New("Too less points") ) +// Tin stores a mesh of triangles with common vertices. type Tin struct { - EPSG uint32 - Vertices []Vertex + // EPSG holds the projection. + EPSG uint32 + // Vertices are the shared vertices. + Vertices []Vertex + // Triangles are the triangles. Triangles [][]int32 + // Min is the lower left corner of the bbox. Min Vertex + // Max is the upper right corner of the bbox. Max Vertex } +// FromWKB constructs the TIN from a WKB representation. +// Shared vertices are identified and referenced by the +// same index. func (t *Tin) FromWKB(data []byte) error { log.Printf("info: data length %d\n", len(data)) @@ -201,6 +210,8 @@ loadTinByIDSQL = tinSQLPrefix + `WHERE id = $2` + tinSQLSuffix ) +// GenerateTinByID generated a TIN by triangulating a point cloud +// from the database. func GenerateTinByID( ctx context.Context, conn *sql.Conn, @@ -219,6 +230,7 @@ return &tin, nil } +// Scan implements the sql.Scanner interface. func (t *Tin) Scan(raw interface{}) error { if raw == nil { return nil
--- a/pkg/octree/tree.go Sun Dec 30 16:24:51 2018 +0100 +++ b/pkg/octree/tree.go Mon Dec 31 11:13:49 2018 +0100 @@ -17,14 +17,18 @@ "math" ) +// Tree is an Octree holding triangles. type Tree struct { + // EPSG is the projection. EPSG uint32 vertices []Vertex triangles [][]int32 index []int32 + // Min is the lower left corner of the bbox. Min Vertex + // Max is the upper right corner of the bbox. Max Vertex } @@ -35,6 +39,7 @@ {0.5, 0.5, 1.0, 1.0}, } +// Vertical does a vertical cross cut from (x1, y1) to (x2, y2). func (ot *Tree) Vertical(x1, y1, x2, y2 float64, fn func(*Triangle)) { box := Box2D{ @@ -123,6 +128,7 @@ } } +// Horizontal does a horizontal cross cut. func (ot *Tree) Horizontal(h float64, fn func(*Triangle)) { if h < ot.Min.Z || ot.Max.Z < h {
--- a/pkg/octree/vertex.go Sun Dec 30 16:24:51 2018 +0100 +++ b/pkg/octree/vertex.go Mon Dec 31 11:13:49 2018 +0100 @@ -23,20 +23,30 @@ ) type ( + // Vertex is a 3D vertex. Vertex struct { X float64 Y float64 Z float64 } + // Triangle is a triangle consisting of three vertices. Triangle [3]Vertex + // Line is a line defined by first vertex on that line + // and the second being the direction. Line [2]Vertex - MultiPointZ []Vertex - LineStringZ []Vertex + // MultiPointZ is a set of vertices. + MultiPointZ []Vertex + + // LineStringZ is a line string formed of vertices. + LineStringZ []Vertex + + // MultiLineStringZ is a set of line strings. MultiLineStringZ []LineStringZ + // Box2D is 2D area from (X1, Y1) to (X2, Y2). Box2D struct { X1 float64 Y1 float64 @@ -44,6 +54,7 @@ Y2 float64 } + // Plane2D is a 2D plane (a line in 2D space). Plane2D struct { A float64 B float64 @@ -51,6 +62,8 @@ } ) +// Minimize adjust this vertex v to hold the minimum +// values component-wise of v and w. func (v *Vertex) Minimize(w Vertex) { if w.X < v.X { v.X = w.X @@ -63,6 +76,8 @@ } } +// Maximize adjust this vertex v to hold the maximum +// values component-wise of v and w. func (v *Vertex) Maximize(w Vertex) { if w.X > v.X { v.X = w.X @@ -75,6 +90,7 @@ } } +// Sub returns (v - w) component-wise. func (v Vertex) Sub(w Vertex) Vertex { return Vertex{ v.X - w.X, @@ -83,6 +99,7 @@ } } +// Add returns (v + w) component-wise. func (v Vertex) Add(w Vertex) Vertex { return Vertex{ v.X + w.X, @@ -91,6 +108,7 @@ } } +// Scale returns s*v component-wise. func (v Vertex) Scale(s float64) Vertex { return Vertex{ s * v.X, @@ -99,6 +117,8 @@ } } +// Interpolate returns a function that return s*v2 + v1 +// component-wise. func Interpolate(v1, v2 Vertex) func(Vertex) Vertex { v2 = v2.Sub(v1) return func(s Vertex) Vertex { @@ -110,10 +130,13 @@ } } +// Less returns if one of v component is less than the +// corresponing component in w. func (v Vertex) Less(w Vertex) bool { return v.X < w.X || v.Y < w.Y || v.Z < w.Z } +// NewLine return a line of point/direction. func NewLine(p1, p2 Vertex) Line { return Line{ p2.Sub(p1), @@ -121,10 +144,13 @@ } } +// Eval returns the vertex for t*l[0] + l[1]. func (l Line) Eval(t float64) Vertex { return l[0].Scale(t).Add(l[1]) } +// IntersectHorizontal returns the intersection point +// for a given z value. func (l Line) IntersectHorizontal(h float64) Vertex { t := (h - l[1].Z) / l[0].Z return l.Eval(t) @@ -140,6 +166,11 @@ return 0 } +// IntersectHorizontal calculates the line string that +// results when cutting a triangle a a certain height. +// Can be empty (on intersection), +// one vertex (only touching an vertex) or +// two vertices (real intersection). func (t *Triangle) IntersectHorizontal(h float64) LineStringZ { sides := [3]int{ side(t[0].Z, h), @@ -213,12 +244,17 @@ } } +// EpsEquals returns true if v and w are equal component-wise +// with the values within a epsilon range. func (v Vertex) EpsEquals(w Vertex) bool { const eps = 1e-5 return math.Abs(v.X-w.X) < eps && math.Abs(v.Y-w.Y) < eps && math.Abs(v.Z-w.Z) < eps } +// JoinOnLine joins the the elements of a given multi line string +// under the assumption that the segments are all on the line segment +// from (x1, y1) to (x2, y2). func (mls MultiLineStringZ) JoinOnLine(x1, y1, x2, y2 float64) MultiLineStringZ { position := linearScale(x1, y1, x2, y2) @@ -269,6 +305,8 @@ return out } +// Write writes a Vertex as three 64 bit values in little endian order +// to the given writer. func (v *Vertex) Write(w io.Writer) error { if err := binary.Write( w, binary.LittleEndian, math.Float64bits(v.X)); err != nil { @@ -282,6 +320,8 @@ w, binary.LittleEndian, math.Float64bits(v.Z)) } +// Read fills this vertex with three 64 bit values stored as +// little endian from the given reader. func (v *Vertex) Read(r io.Reader) error { var buf [8]byte b := buf[:] @@ -300,6 +340,7 @@ return nil } +// AsWKB returns the WKB representation of the given multi line string. func (mls MultiLineStringZ) AsWKB() []byte { // pre-calculate size to avoid reallocations. @@ -328,6 +369,8 @@ return buf.Bytes() } +// AsWKB2D returns the WKB representation of the given multi line string +// leaving the z component out. func (mls MultiLineStringZ) AsWKB2D() []byte { // pre-calculate size to avoid reallocations. @@ -355,7 +398,7 @@ return buf.Bytes() } -// Join joins two lines leaving the first of the secoung out. +// Join joins two lines leaving the first of the second out. func (ls LineStringZ) Join(other LineStringZ) LineStringZ { nline := make(LineStringZ, len(ls)+len(other)-1) copy(nline, ls) @@ -363,6 +406,8 @@ return nline } +// Merge merges line segments of a given multi line string +// by finding common start and end vertices. func (mls MultiLineStringZ) Merge() MultiLineStringZ { var out MultiLineStringZ @@ -467,15 +512,13 @@ return out } +// Intersects checks if two Box2Ds intersect. 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 -} - +// Xi returns the i-th x component. func (a Box2D) Xi(i int) float64 { if i == 0 { return a.X1 @@ -483,6 +526,7 @@ return a.X2 } +// Yi returns the i-th y component. func (a Box2D) Yi(i int) float64 { if i == 0 { return a.Y1 @@ -490,6 +534,7 @@ return a.Y2 } +// NewPlane2D creates a new Plane2D from two given points. func NewPlane2D(x1, y1, x2, y2 float64) Plane2D { b := x2 - x1 a := -(y2 - y1) @@ -503,6 +548,9 @@ return Plane2D{a, b, c} } +// Eval determines the distance of a given point +// from the plane. The sign of the result indicates +// the sideness. func (p Plane2D) Eval(x, y float64) float64 { return p.A*x + p.B*y + p.C } @@ -516,6 +564,8 @@ return s | 1 } +// IntersectsPlane checks if a Box2D intersects with +// a given Plane2D. func (a Box2D) IntersectsPlane(p Plane2D) bool { var s int for i := 0; i < 2; i++ { @@ -537,6 +587,7 @@ return false } +// Cross calculates the cross product of two vertices. func (v Vertex) Cross(w Vertex) Vertex { return Vertex{ v.Y*w.Z - v.Z*w.Y, @@ -545,6 +596,9 @@ } } +// Intersection calcultes the 2D intersection point of +// two Plane2Ds. If they do not intersect the returned +// bool flags is set to false. func (p Plane2D) Intersection(o Plane2D) (float64, float64, bool) { u1 := Vertex{p.A, p.B, p.C} @@ -559,6 +613,7 @@ return plane.X / plane.Z, plane.Y / plane.Z, true } +// VerticalLine is a 2D line segment. type VerticalLine struct { x1 float64 y1 float64 @@ -568,6 +623,7 @@ line Plane2D } +// NewVerticalLine creates a new 2D line segment. func NewVerticalLine(x1, y1, x2, y2 float64) *VerticalLine { return &VerticalLine{ x1: x1, @@ -605,6 +661,7 @@ func inRange(a float64) bool { return 0 <= a && a <= 1 } +// Intersection intersects a line segment with a triangle. func (vl *VerticalLine) Intersection(t *Triangle) LineStringZ { var out LineStringZ @@ -780,6 +837,7 @@ return out } +// AsWKB returns a WKB representation of the given point cloud. func (mpz MultiPointZ) AsWKB() []byte { size := 1 + 4 + 4 + len(mpz)*(1+4+3*8)