comparison pkg/imports/sr.go @ 5416:31b0e865e7a0 marking-single-beam

Stored marking points in database.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 07 Jul 2021 14:57:30 +0200
parents 4ad68ab239b7
children 2d294ad81241
comparison
equal deleted inserted replaced
5415:4ad68ab239b7 5416:31b0e865e7a0
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"
27 "math" 28 "math"
28 "os" 29 "os"
29 "path" 30 "path"
30 "path/filepath" 31 "path/filepath"
31 "strconv" 32 "strconv"
196 4326 197 4326
197 ) 198 )
198 FROM waterway.sounding_results sr 199 FROM waterway.sounding_results sr
199 WHERE id = $1 200 WHERE id = $1
200 ` 201 `
202 insertMarkingPointsSQL = `
203 INSERT INTO waterway.sounding_results_marking_points (
204 sounding_result_id,
205 height,
206 points
207 )
208 SELECT
209 $1,
210 $2,
211 ST_Transform(ST_Force2D(ST_GeomFromWKB($4, $3::integer)), 4326)
212 FROM waterway.sounding_results sr
213 WHERE id = $1
214 `
201 215
202 selectGaugeLDCSQL = ` 216 selectGaugeLDCSQL = `
203 SELECT 217 SELECT
204 grwl.value, 218 grwl.value,
205 grwl.depth_reference 219 grwl.depth_reference
429 443
430 feedback.Info("Reproject XYZ data.") 444 feedback.Info("Reproject XYZ data.")
431 445
432 start := time.Now() 446 start := time.Now()
433 447
434 xyzWKB := xyz.AsWKB()
435 var reproj []byte 448 var reproj []byte
436 var epsg uint32 449 var epsg uint32
437 450
438 if err := tx.QueryRowContext( 451 if err := tx.QueryRowContext(
439 ctx, 452 ctx,
440 reprojectPointsSingleBeamSQL, 453 reprojectPointsSingleBeamSQL,
441 xyzWKB, 454 xyz.AsWKB(),
442 m.EPSG, 455 m.EPSG,
443 ).Scan(&reproj, &epsg); err != nil { 456 ).Scan(&reproj, &epsg); err != nil {
444 return nil, err 457 return nil, err
445 } 458 }
446 459
681 _, err = tx.ExecContext(ctx, insertMeshSQL, id, checksum, index) 694 _, err = tx.ExecContext(ctx, insertMeshSQL, id, checksum, index)
682 if err != nil { 695 if err != nil {
683 return nil, err 696 return nil, err
684 } 697 }
685 feedback.Info("Storing mesh index took %s.", time.Since(start)) 698 feedback.Info("Storing mesh index took %s.", time.Since(start))
686 err = generateIsos(ctx, tx, feedback, &final, id) 699 if err := generateIsos(ctx, tx, feedback, &final, id); err != nil {
687 if err != nil {
688 return nil, err 700 return nil, err
689 } 701 }
690 } else { // SurveyTypeMarking 702 } else { // SurveyTypeMarking
691 return nil, errors.New("not implemented, yet") 703 if err := generateMarkingPoints(
704 ctx, tx, feedback,
705 xyz, removed, epsg,
706 id,
707 ); err != nil {
708 return nil, err
709 }
692 } 710 }
693 711
694 // Store for potential later removal. 712 // Store for potential later removal.
695 if err = track(ctx, tx, importID, "waterway.sounding_results", id); err != nil { 713 if err = track(ctx, tx, importID, "waterway.sounding_results", id); err != nil {
696 return nil, err 714 return nil, err
906 heights = append(heights, h) 924 heights = append(heights, h)
907 } 925 }
908 return heights 926 return heights
909 } 927 }
910 928
929 func loadClassBreaks(
930 ctx context.Context,
931 tx *sql.Tx,
932 feedback Feedback,
933 minZ, maxZ float64,
934 ) mesh.ClassBreaks {
935
936 heights, err := mesh.LoadClassBreaks(
937 ctx, tx,
938 "morphology_classbreaks")
939
940 if err != nil {
941 feedback.Warn("Loading class breaks failed: %v", err)
942 feedback.Info("Using default class breaks")
943 heights = defaultClassBreaks(minZ, maxZ)
944 } else {
945 heights = heights.ExtrapolateClassBreaks(minZ, maxZ)
946 }
947
948 return heights.Dedup()
949 }
950
951 func generateMarkingPoints(
952 ctx context.Context,
953 tx *sql.Tx,
954 feedback Feedback,
955 xyz mesh.MultiPointZ,
956 removed map[int32]struct{},
957 epsg uint32,
958 id int64,
959 ) error {
960 log.Printf("debug: generateMarkingPoints")
961
962 min, max := mesh.MinMaxVertex(xyz.FilterRemoved(removed))
963
964 log.Printf("debug: min/max %.2f/%.2f\n", min.Z, max.Z)
965
966 heights := loadClassBreaks(ctx, tx, feedback, min.Z, max.Z)
967
968 classes := heights.Classify(xyz.FilterRemoved(removed))
969
970 log.Printf("debug: removed %d\n", len(removed))
971
972 // Should not happen ... Z values over the top.
973 if n := len(classes) - 1; n > 1 && len(classes[n]) > 0 {
974 // Place the over the top values to the class below.
975 classes[n-1] = append(classes[n-1], classes[n]...)
976 classes[n] = nil
977 classes = classes[:n]
978 }
979
980 stmt, err := tx.PrepareContext(ctx, insertMarkingPointsSQL)
981 if err != nil {
982 return err
983 }
984 defer stmt.Close()
985
986 for i, class := range classes {
987 // Ignore empty classes
988 if len(class) == 0 {
989 continue
990 }
991 log.Printf("debug: class %d: %d\n", i, len(class))
992 _, err := stmt.ExecContext(ctx, id, heights[i], epsg, class.AsWKB())
993 if err != nil {
994 return err
995 }
996 }
997
998 return nil
999 }
1000
911 func generateIsos( 1001 func generateIsos(
912 ctx context.Context, 1002 ctx context.Context,
913 tx *sql.Tx, 1003 tx *sql.Tx,
914 feedback Feedback, 1004 feedback Feedback,
915 tree *mesh.STRTree, 1005 tree *mesh.STRTree,
916 id int64, 1006 id int64,
917 ) error { 1007 ) error {
918 1008
919 heights, err := mesh.LoadClassBreaks( 1009 heights := loadClassBreaks(ctx, tx, feedback, tree.Min().Z, tree.Max().Z)
920 ctx, tx,
921 "morphology_classbreaks",
922 )
923
924 minZ, maxZ := tree.Min().Z, tree.Max().Z
925
926 if err != nil {
927 feedback.Warn("Loading class breaks failed: %v", err)
928 feedback.Info("Using default class breaks")
929 heights = defaultClassBreaks(minZ, maxZ)
930 } else {
931 heights = heights.ExtrapolateClassBreaks(minZ, maxZ)
932 }
933
934 /*
935 for i, v := range heights {
936 fmt.Printf("%d %.2f\n", i, v)
937 }
938 log.Printf("%.2f - %.2f\n", tree.Min.Z, tree.Max.Z)
939 */
940
941 heights = heights.Dedup()
942 1010
943 return generateIsoAreas(ctx, tx, feedback, tree, heights, id) 1011 return generateIsoAreas(ctx, tx, feedback, tree, heights, id)
944 } 1012 }
945 1013
946 func generateIsoAreas( 1014 func generateIsoAreas(