# HG changeset patch # User Sascha L. Teichmann # Date 1552311394 -3600 # Node ID 2833ff156cb205155346c2e16bfe43acbd90c334 # Parent 4486ca003b55442c9e9c745253a09915b067d415 Morphological differences: Moved loading of clipping polygon into octree package. diff -r 4486ca003b55 -r 2833ff156cb2 cmd/octreediff/main.go --- a/cmd/octreediff/main.go Mon Mar 11 14:18:14 2019 +0100 +++ b/cmd/octreediff/main.go Mon Mar 11 14:36:34 2019 +0100 @@ -65,22 +65,6 @@ 4326 ) ` - clippingPolygonSQL = ` -WITH joined AS ( - SELECT - sr.area AS area, - sr.date_info AS date_info - FROM waterway.sounding_results sr JOIN - waterway.bottlenecks bn ON sr.bottleneck_id = bn.id - WHERE bn.bottleneck_id = $1 -) -SELECT ST_AsBinary( - ST_intersection( - (SELECT ST_Transform(area::geometry, $2::int) FROM joined WHERE date_info = $3::date), - (SELECT ST_Transform(area::geometry, $2::int) FROM joined WHERE date_info = $4::date) - ) - ) AS area -` insertContourSQLClipped = ` WITH joined AS ( SELECT @@ -226,23 +210,17 @@ last = now log.Printf("num points: %d\n", len(result)) - var clip []byte - - if err := tx.QueryRowContext( - ctx, clippingPolygonSQL, + clippingPolygon, err := octree.LoadClippingPolygon( + ctx, + conn, + first.EPSG, bottleneck, - first.EPSG, firstDate, secondDate, - ).Scan(&clip); err != nil { + ) + if err != nil { return err } - var clippingPolygon octree.Polygon - if err := clippingPolygon.FromWKB(clip); err != nil { - return err - } - clippingPolygon.Indexify() - now = time.Now() log.Printf("loading clipping polygon took %v\n", now.Sub(last)) last = now @@ -266,7 +244,7 @@ log.Printf("building STR tree took %v\n", now.Sub(last)) last = now - removed := str.Clip(&clippingPolygon) + removed := str.Clip(clippingPolygon) now = time.Now() log.Printf("clipping STR tree took %v\n", now.Sub(last)) last = now diff -r 4486ca003b55 -r 2833ff156cb2 pkg/controllers/diff.go --- a/pkg/controllers/diff.go Mon Mar 11 14:18:14 2019 +0100 +++ b/pkg/controllers/diff.go Mon Mar 11 14:36:34 2019 +0100 @@ -18,6 +18,7 @@ "fmt" "log" "net/http" + "sync" "time" "golang.org/x/sync/semaphore" @@ -103,14 +104,59 @@ points := minuendTree.Diff(subtrahendTree) log.Printf("info: A - B took %v\n", time.Since(start)) - start = time.Now() - var tri *octree.Triangulation - if tri, err = points.Triangulate(); err != nil { + // The Triangulation and the loading of the clipping + // polygon can be done concurrently. + + jobs := make(chan func()) + + wg := new(sync.WaitGroup) + for i := 0; i < 2; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for job := range jobs { + job() + } + }() + } + + var ( + tri *octree.Triangulation + triErr error + clip *octree.Polygon + clipErr error + ) + + jobs <- func() { + start := time.Now() + tri, triErr = points.Triangulate() + log.Printf("info: triangulation took %v\n", time.Since(start)) + } + + jobs <- func() { + start := time.Now() + clip, clipErr = octree.LoadClippingPolygon( + ctx, conn, + minuendTree.EPSG, + dci.Bottleneck, + dci.Minuend.Time, + dci.Subtrahend.Time) + log.Printf("info: loading clipping polygon took %v\n", time.Since(start)) + } + close(jobs) + wg.Wait() + + switch { + case triErr != nil && clipErr != nil: + err = fmt.Errorf("%v %v", triErr, clipErr) + return + case triErr != nil: + err = triErr + return + case clipErr != nil: + err = clipErr return } - log.Printf("triangulation took %v\n", time.Since(start)) - - _ = tri // TODO: Implement me! diff -r 4486ca003b55 -r 2833ff156cb2 pkg/octree/polygon.go --- a/pkg/octree/polygon.go Mon Mar 11 14:18:14 2019 +0100 +++ b/pkg/octree/polygon.go Mon Mar 11 14:36:34 2019 +0100 @@ -15,10 +15,13 @@ import ( "bytes" + "context" + "database/sql" "encoding/binary" "fmt" "log" "math" + "time" "github.com/tidwall/rtree" @@ -29,9 +32,7 @@ ring []float64 Polygon struct { - // TODO: Implement me! - rings []ring - + rings []ring indices []*rtree.RTree } @@ -41,11 +42,57 @@ ) const ( + clippingPolygonSQL = ` +WITH joined AS ( + SELECT + sr.area AS area, + sr.date_info AS date_info + FROM waterway.sounding_results sr JOIN + waterway.bottlenecks bn ON sr.bottleneck_id = bn.id + WHERE bn.bottleneck_id = $1 +) +SELECT ST_AsBinary( + ST_intersection( + (SELECT ST_Transform(area::geometry, $2::int) FROM joined WHERE date_info = $3::date), + (SELECT ST_Transform(area::geometry, $2::int) FROM joined WHERE date_info = $4::date) + ) + ) AS area +` +) + +const ( IntersectionInside IntersectionType = iota IntersectionOutSide IntersectionOverlaps ) +func LoadClippingPolygon( + ctx context.Context, + conn *sql.Conn, + epsg uint32, + bottleneck string, + first, second time.Time, +) (*Polygon, error) { + + var clip []byte + + if err := conn.QueryRowContext( + ctx, clippingPolygonSQL, + bottleneck, + epsg, + first, second, + ).Scan(&clip); err != nil { + return nil, err + } + + var polygon Polygon + if err := polygon.FromWKB(clip); err != nil { + return nil, err + } + polygon.Indexify() + return &polygon, nil +} + func (ls lineSegment) Rect(interface{}) ([]float64, []float64) { var min, max [2]float64