Mercurial > gemma
comparison pkg/imports/sr.go @ 4570:4b3a298b94f8 iso-areas
Moved area tracing to octree package.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 06 Oct 2019 11:12:32 +0200 |
parents | 2c49a293f275 |
children | c657dec6b0fa |
comparison
equal
deleted
inserted
replaced
4569:efb7851f54dd | 4570:4b3a298b94f8 |
---|---|
26 "io" | 26 "io" |
27 "math" | 27 "math" |
28 "os" | 28 "os" |
29 "path" | 29 "path" |
30 "path/filepath" | 30 "path/filepath" |
31 "runtime" | |
32 "strconv" | 31 "strconv" |
33 "strings" | 32 "strings" |
34 "sync" | |
35 "time" | 33 "time" |
36 | 34 |
37 "github.com/fogleman/contourmap" | |
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" |
41 "gemma.intevation.de/gemma/pkg/models" | 38 "gemma.intevation.de/gemma/pkg/models" |
42 "gemma.intevation.de/gemma/pkg/octree" | 39 "gemma.intevation.de/gemma/pkg/octree" |
923 defer func() { | 920 defer func() { |
924 feedback.Info("Generating iso areas took %s.", | 921 feedback.Info("Generating iso areas took %s.", |
925 time.Since(total)) | 922 time.Since(total)) |
926 }() | 923 }() |
927 | 924 |
928 min, max := tree.Min, tree.Max | 925 areas := tree.TraceAreas(heights, isoCellSize) |
929 | |
930 width := max.X - min.X | |
931 height := max.Y - min.Y | |
932 | |
933 feedback.Info("Width/Height: %.2f / %.2f", width, height) | |
934 | |
935 xcells := int(math.Ceil(width / isoCellSize)) | |
936 ycells := int(math.Ceil(height / isoCellSize)) | |
937 | |
938 feedback.Info("Raster size: (%d, %d)", xcells, ycells) | |
939 | |
940 // Add border for closing | |
941 raster := make([]float64, (xcells+2)*(ycells+2)) | |
942 | |
943 // prefill for no data | |
944 const nodata = -math.MaxFloat64 | |
945 for i := range raster { | |
946 raster[i] = nodata | |
947 } | |
948 | |
949 // rasterize the height model | |
950 | |
951 var wg sync.WaitGroup | |
952 | |
953 rows := make(chan int) | |
954 | |
955 rasterRow := func() { | |
956 defer wg.Done() | |
957 for i := range rows { | |
958 pos := (i+1)*(xcells+2) + 1 | |
959 row := raster[pos : pos+xcells] | |
960 py := min.Y + float64(i)*isoCellSize + isoCellSize/2 | |
961 px := min.X + isoCellSize/2 | |
962 for j := range row { | |
963 v, ok := tree.Value(px, py) | |
964 if ok { | |
965 row[j] = v | |
966 } | |
967 px += isoCellSize | |
968 } | |
969 } | |
970 } | |
971 | |
972 start := time.Now() | |
973 | |
974 for n := runtime.NumCPU(); n >= 1; n-- { | |
975 wg.Add(1) | |
976 go rasterRow() | |
977 } | |
978 | |
979 for i := 0; i < ycells; i++ { | |
980 rows <- i | |
981 } | |
982 close(rows) | |
983 | |
984 wg.Wait() | |
985 | |
986 feedback.Info("Rasterizing took %v.", time.Since(start)) | |
987 | |
988 feedback.Info("Trace iso areas.") | |
989 | |
990 start = time.Now() | |
991 | |
992 tracer := contourmap.FromFloat64s(xcells+2, ycells+2, raster) | |
993 | |
994 areas := make([]wkb.MultiPolygonGeom, len(heights)) | |
995 | |
996 // TODO: Check if this correct! | |
997 reprojX := common.Linear(1, min.X, float64(xcells+1), max.X) | |
998 reprojY := common.Linear(1, min.Y, float64(ycells+1), max.Y) | |
999 | |
1000 cnts := make(chan int) | |
1001 | |
1002 doContours := func() { | |
1003 defer wg.Done() | |
1004 for hIdx := range cnts { | |
1005 c := tracer.Contours(heights[hIdx]) | |
1006 | |
1007 if len(c) == 0 { | |
1008 continue | |
1009 } | |
1010 | |
1011 // We need to bring it back to the | |
1012 // none raster coordinate system. | |
1013 a := make(wkb.MultiPolygonGeom, len(c)) | |
1014 | |
1015 for i, pl := range c { | |
1016 shell := make(wkb.LinearRingGeom, len(pl)) | |
1017 for j, pt := range pl { | |
1018 shell[j] = wkb.PointGeom{ | |
1019 X: reprojX(pt.X), | |
1020 Y: reprojY(pt.Y), | |
1021 } | |
1022 } | |
1023 a[i] = wkb.PolygonGeom{shell} | |
1024 } | |
1025 | |
1026 areas[hIdx] = a | |
1027 } | |
1028 } | |
1029 | |
1030 for n := runtime.NumCPU(); n >= 1; n-- { | |
1031 wg.Add(1) | |
1032 go doContours() | |
1033 } | |
1034 | |
1035 for i := range heights { | |
1036 cnts <- i | |
1037 } | |
1038 close(cnts) | |
1039 | |
1040 wg.Wait() | |
1041 | |
1042 feedback.Info("Tracing areas took %v.", time.Since(start)) | |
1043 | |
1044 // Raster and tracer are not needed any more. | |
1045 raster, tracer = nil, nil | |
1046 | 926 |
1047 return storeAreas( | 927 return storeAreas( |
1048 ctx, tx, feedback, | 928 ctx, tx, feedback, |
1049 areas, tree.EPSG, heights, id) | 929 areas, tree.EPSG, heights, id) |
1050 } | 930 } |