Mercurial > gemma
diff pkg/imports/sr.go @ 3646:810b28f59b8b single-beam
Generate random points for second mesh.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 12 Jun 2019 17:30:20 +0200 |
parents | e1021fd60190 |
children | 01ce3ba9b0d0 |
line wrap: on
line diff
--- a/pkg/imports/sr.go Wed Jun 12 12:57:14 2019 +0200 +++ b/pkg/imports/sr.go Wed Jun 12 17:30:20 2019 +0200 @@ -24,12 +24,15 @@ "errors" "fmt" "io" + "log" "math" "os" "path" "path/filepath" + "runtime" "strconv" "strings" + "sync" "time" shp "github.com/jonas-p/go-shp" @@ -67,6 +70,11 @@ contourTolerance = 0.1 ) +const ( + tooLongEdge = 50.0 + pointsPerSquareMeter = 5 +) + // SRJobKind is the unique name of a SoundingResult import job. const SRJobKind JobKind = "sr" @@ -360,11 +368,122 @@ feedback.Info("Triangulation took %v.", time.Since(start)) feedback.Info("Number triangles: %d.", len(tri.Triangles)/3) + var clippingPolygon octree.Polygon + if boundary == nil { feedback.Info("No boundary given.") - feedback.Info("Eliminate triangles with long edges.") + + polygon, removed := tri.ConcaveHull(tooLongEdge) + + polygonArea := polygon.Area() + if polygonArea < 0.0 { // counter clockwise + polygonArea = -polygonArea + polygon.Reverse() + } + + firstTin := tri.Tin() + builder := octree.NewBuilder(firstTin) + builder.Build(removed) + + firstTree := builder.Tree() + + bbox := polygon.BBox() + bboxArea := bbox.Area() + + log.Printf("bbox area: %.2f\n", bboxArea) + log.Printf("polygon area: %.2f\n", polygonArea) + + numPoints := int(math.Ceil(polygonArea * pointsPerSquareMeter)) + + log.Printf("random points for density of ~%d points/m²: %d\n", + pointsPerSquareMeter, numPoints) + + start := time.Now() + + var wg sync.WaitGroup + + jobs := make(chan int) + out := make(chan []octree.Vertex) + done := make(chan struct{}) + + cpus := runtime.NumCPU() + + free := make(chan []octree.Vertex, cpus) + + for i, n := 0, cpus; i < n; i++ { + wg.Add(1) + go func() { + defer wg.Done() + xRange := common.Random(bbox.X1, bbox.X2) + yRange := common.Random(bbox.Y1, bbox.Y2) - tri.ConcaveHull(50.0) + for size := range jobs { + var vertices []octree.Vertex + select { + case vertices = <-free: + default: + vertices = make([]octree.Vertex, 0, 1000) + } + for len(vertices) < size { + x, y := xRange(), yRange() + if z, ok := firstTree.Value(x, y); ok { + vertices = append(vertices, octree.Vertex{X: x, Y: y, Z: z}) + } + } + out <- vertices + } + }() + } + + generated := make(octree.LineStringZ, 0, numPoints+len(polygon)-1) + + go func() { + defer close(done) + for vertices := range out { + generated = append(generated, vertices...) + select { + case free <- vertices[:0]: + default: + } + } + }() + + for remain := numPoints; remain > 0; { + if remain > 1000 { + jobs <- 1000 + remain -= 1000 + } else { + jobs <- remain + remain = 0 + } + } + close(jobs) + wg.Wait() + close(out) + <-done + + log.Printf("Generating %d points took %v\n", len(generated), time.Since(start)) + + // Add the boundary to new point cloud. + generated = append(generated, polygon[:len(polygon)-1]...) + + xyz = octree.MultiPointZ(generated) + + } else { + var hull []byte + if err = tx.QueryRowContext( + ctx, + reprojectPointsSQL, + boundary.asWKB(), + m.EPSG, + epsg, + ).Scan(&hull); err != nil { + return nil, err + } + if err := clippingPolygon.FromWKB(hull); err != nil { + return nil, err + } + clippingPolygon.Indexify() } // TODO: Implement me! @@ -419,6 +538,7 @@ start = time.Now() var clippingPolygon octree.Polygon + if err := clippingPolygon.FromWKB(hull); err != nil { return nil, err }