comparison pkg/imports/sr.go @ 3655:a6c671abbc35 single-beam

Started with cleaning up the single beam import.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 13 Jun 2019 18:33:54 +0200
parents 26e02fa5b992
children 1c3df921361d
comparison
equal deleted inserted replaced
3654:26e02fa5b992 3655:a6c671abbc35
22 "database/sql" 22 "database/sql"
23 "encoding/hex" 23 "encoding/hex"
24 "errors" 24 "errors"
25 "fmt" 25 "fmt"
26 "io" 26 "io"
27 "log"
28 "math" 27 "math"
29 "os" 28 "os"
30 "path" 29 "path"
31 "path/filepath" 30 "path/filepath"
32 "runtime"
33 "strconv" 31 "strconv"
34 "strings" 32 "strings"
35 "sync"
36 "time" 33 "time"
37 34
38 shp "github.com/jonas-p/go-shp" 35 shp "github.com/jonas-p/go-shp"
39 36
40 "gemma.intevation.de/gemma/pkg/common" 37 "gemma.intevation.de/gemma/pkg/common"
148 145
149 repairBoundarySQL = ` 146 repairBoundarySQL = `
150 SELECT 147 SELECT
151 ST_AsBinary(ST_Buffer(ST_MakeValid(ST_GeomFromWKB($1, $2::integer)), 0.0)), 148 ST_AsBinary(ST_Buffer(ST_MakeValid(ST_GeomFromWKB($1, $2::integer)), 0.0)),
152 ST_AsBinary(ST_Buffer(ST_MakeValid(ST_GeomFromWKB($1, $2::integer)), 0.1))` 149 ST_AsBinary(ST_Buffer(ST_MakeValid(ST_GeomFromWKB($1, $2::integer)), 0.1))`
153
154 whatsWrongSQL = `
155 SELECT
156 ST_IsValidReason(
157 CAST(ST_MakeValid(ST_Transform(ST_GeomFromWKB($1, $2::integer), 4326))::geography AS geometry)),
158 ST_IsValid(
159 CAST(ST_MakeValid(ST_Transform(ST_GeomFromWKB($1, $2::integer), 4326))::geography AS geometry))
160 `
161 150
162 insertContourSQL = ` 151 insertContourSQL = `
163 INSERT INTO waterway.sounding_results_contour_lines ( 152 INSERT INTO waterway.sounding_results_contour_lines (
164 sounding_result_id, 153 sounding_result_id,
165 height, 154 height,
382 feedback.Info("Number triangles: %d.", len(tri.Triangles)/3) 371 feedback.Info("Number triangles: %d.", len(tri.Triangles)/3)
383 372
384 var clippingPolygon octree.Polygon 373 var clippingPolygon octree.Polygon
385 374
386 if boundary == nil { 375 if boundary == nil {
387 feedback.Info("No boundary given.") 376 feedback.Info("No boundary given. Calulating from XYZ data.")
377 feedback.Info("Eliminate triangles with edges longer than %.2f meters.", tooLongEdge)
388 378
389 polygon, removed := tri.ConcaveHull(tooLongEdge) 379 polygon, removed := tri.ConcaveHull(tooLongEdge)
390 380
391 polygonArea := polygon.Area() 381 polygonArea := polygon.Area()
392 if polygonArea < 0.0 { // counter clockwise 382 if polygonArea < 0.0 { // counter clockwise
393 polygonArea = -polygonArea 383 polygonArea = -polygonArea
394 polygon.Reverse() 384 polygon.Reverse()
395 } 385 }
396 386
397 clippingPolygon.FromLineStringZ(polygon) 387 clippingPolygon.FromLineStringZ(polygon)
398
399 var wrong string
400 var valid bool
401 if err := tx.QueryRowContext(
402 ctx,
403 whatsWrongSQL,
404 clippingPolygon.AsWKB(),
405 epsg,
406 ).Scan(&wrong, &valid); err != nil {
407 return nil, err
408 }
409
410 log.Printf("!!!!!!!!: whats wrong (%t): %s\n", valid, wrong)
411 388
412 var repaired, buffered []byte 389 var repaired, buffered []byte
413 390
414 if err := tx.QueryRowContext( 391 if err := tx.QueryRowContext(
415 ctx, 392 ctx,
432 builder := octree.NewBuilder(firstTin) 409 builder := octree.NewBuilder(firstTin)
433 builder.Build(removed) 410 builder.Build(removed)
434 411
435 firstTree := builder.Tree() 412 firstTree := builder.Tree()
436 413
437 bbox := polygon.BBox() 414 feedback.Info("Boundary area: %.2fm²", polygonArea)
438 bboxArea := bbox.Area()
439
440 log.Printf("bbox area: %.2f\n", bboxArea)
441 log.Printf("polygon area: %.2f\n", polygonArea)
442 415
443 numPoints := int(math.Ceil(polygonArea * pointsPerSquareMeter)) 416 numPoints := int(math.Ceil(polygonArea * pointsPerSquareMeter))
444 417
445 log.Printf("random points for density of ~%d points/m²: %d\n", 418 feedback.Info("Generating %d random points for an average density of ~%d points/m².",
446 pointsPerSquareMeter, numPoints) 419 numPoints, pointsPerSquareMeter)
447 420
448 start := time.Now() 421 start := time.Now()
449 422
450 var wg sync.WaitGroup
451
452 jobs := make(chan int)
453 out := make(chan []octree.Vertex)
454 done := make(chan struct{})
455
456 cpus := runtime.NumCPU()
457
458 free := make(chan []octree.Vertex, cpus)
459
460 for i, n := 0, cpus; i < n; i++ {
461 wg.Add(1)
462 go func() {
463 defer wg.Done()
464 xRange := common.Random(bbox.X1, bbox.X2)
465 yRange := common.Random(bbox.Y1, bbox.Y2)
466
467 for size := range jobs {
468 var vertices []octree.Vertex
469 select {
470 case vertices = <-free:
471 default:
472 vertices = make([]octree.Vertex, 0, 1000)
473 }
474 for len(vertices) < size {
475 x, y := xRange(), yRange()
476 if z, ok := firstTree.Value(x, y); ok {
477 vertices = append(vertices, octree.Vertex{X: x, Y: y, Z: z})
478 }
479 }
480 out <- vertices
481 }
482 }()
483 }
484
485 generated := make(octree.LineStringZ, 0, numPoints+len(polygon)-1) 423 generated := make(octree.LineStringZ, 0, numPoints+len(polygon)-1)
486 424
487 go func() { 425 firstTree.GenerateRandomVertices(numPoints, func(vertices []octree.Vertex) {
488 defer close(done) 426 generated = append(generated, vertices...)
489 for vertices := range out { 427 })
490 generated = append(generated, vertices...) 428
491 select { 429 feedback.Info("Generating %d points took %v.", len(generated), time.Since(start))
492 case free <- vertices[:0]:
493 default:
494 }
495 }
496 }()
497
498 for remain := numPoints; remain > 0; {
499 if remain > 1000 {
500 jobs <- 1000
501 remain -= 1000
502 } else {
503 jobs <- remain
504 remain = 0
505 }
506 }
507 close(jobs)
508 wg.Wait()
509 close(out)
510 <-done
511
512 log.Printf("Generating %d points took %v\n", len(generated), time.Since(start))
513 430
514 // Add the boundary to new point cloud. 431 // Add the boundary to new point cloud.
515 generated = append(generated, polygon[:len(polygon)-1]...) 432 generated = append(generated, polygon[:len(polygon)-1]...)
516 433
434 feedback.Info("Triangulate new point cloud.")
435
436 start = time.Now()
437
517 xyz = octree.MultiPointZ(generated) 438 xyz = octree.MultiPointZ(generated)
518 439
519 start = time.Now()
520 tri, err := octree.Triangulate(xyz) 440 tri, err := octree.Triangulate(xyz)
521 if err != nil { 441 if err != nil {
522 return nil, err 442 return nil, err
523 } 443 }
524 log.Printf("Second triangulation took %v.", time.Since(start)) 444 feedback.Info("Second triangulation took %v.", time.Since(start))
525 log.Printf("Number triangles: %d.", len(tri.Triangles)/3) 445 feedback.Info("Number triangles: %d.", len(tri.Triangles)/3)
526 446 feedback.Info("Clipping triangles from new mesh.")
447
448 start = time.Now()
527 secondTin := tri.Tin() 449 secondTin := tri.Tin()
528 450 secondTin.EPSG = uint32(epsg)
529 //polygon.Buffer(1.0)
530
531 clippingPolygonBuffered.Indexify() 451 clippingPolygonBuffered.Indexify()
532 452
533 var str octree.STRTree 453 var str octree.STRTree
534 str.Build(secondTin) 454 str.Build(secondTin)
535 log.Printf("Building STR tree took %v", time.Since(start)) 455 feedback.Info("Building STR tree took %v", time.Since(start))
536 456
537 start = time.Now() 457 start = time.Now()
538 458
539 removed = str.Clip(&clippingPolygonBuffered) 459 removed = str.Clip(&clippingPolygonBuffered)
540 log.Printf("Clipping STR tree took %v.", time.Since(start)) 460 feedback.Info("Clipping STR tree took %v.", time.Since(start))
541 log.Printf("Number of triangles to clip %d.", len(removed)) 461 feedback.Info("Number of triangles to clip %d.", len(removed))
542 462
543 start = time.Now() 463 start = time.Now()
544 464
545 secondTin.EPSG = uint32(epsg) 465 feedback.Info("Building final octree index")
546 466
547 builder = octree.NewBuilder(secondTin) 467 builder = octree.NewBuilder(secondTin)
548 builder.Build(removed) 468 builder.Build(removed)
549 octreeIndex, err := builder.Bytes() 469 octreeIndex, err := builder.Bytes()
550 if err != nil { 470 if err != nil {
551 return nil, err 471 return nil, err
552 } 472 }
553 feedback.Info("Building octree took %v.", time.Since(start)) 473 feedback.Info("Building octree took %v.", time.Since(start))
474
475 start = time.Now()
554 476
555 var ( 477 var (
556 id int64 478 id int64
557 dummy uint32 479 dummy uint32
558 lat, lon float64 480 lat, lon float64
577 &hull, 499 &hull,
578 ); err != nil { 500 ); err != nil {
579 return nil, err 501 return nil, err
580 } 502 }
581 503
582 start = time.Now()
583 h := sha1.New() 504 h := sha1.New()
584 h.Write(octreeIndex) 505 h.Write(octreeIndex)
585 checksum := hex.EncodeToString(h.Sum(nil)) 506 checksum := hex.EncodeToString(h.Sum(nil))
586 _, err = tx.ExecContext(ctx, insertOctreeSQL, id, checksum, octreeIndex) 507 _, err = tx.ExecContext(ctx, insertOctreeSQL, id, checksum, octreeIndex)
587 if err != nil { 508 if err != nil {