github.com/searKing/golang/go@v1.2.117/exp/image/geom.go (about) 1 // Copyright 2023 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package image 6 7 import ( 8 "math" 9 10 constraints_ "github.com/searKing/golang/go/exp/constraints" 11 "golang.org/x/exp/constraints" 12 ) 13 14 // UnionPoints returns the smallest rectangle that contains all points. 15 // an empty rectangle is a empty set, Not a point 16 func UnionPoints[E constraints_.Number](pts ...Point[E]) Rectangle[E] { 17 if len(pts) == 0 { 18 return Rectangle[E]{} 19 } 20 21 r := Rectangle[E]{ 22 Min: pts[0], 23 Max: pts[0], 24 } 25 for _, p := range pts[1:] { 26 if p.X < r.Min.X { 27 r.Min.X = p.X 28 } 29 if p.Y < r.Min.Y { 30 r.Min.Y = p.Y 31 } 32 if p.X > r.Max.X { 33 r.Max.X = p.X 34 } 35 if p.Y > r.Max.Y { 36 r.Max.Y = p.Y 37 } 38 } 39 return r 40 } 41 42 // UnionRectangles returns the smallest rectangle that contains all rectangles, empty rectangles excluded. 43 func UnionRectangles[E constraints_.Number](rs ...Rectangle[E]) Rectangle[E] { 44 var ur Rectangle[E] 45 for _, r := range rs { 46 ur = ur.Union(r) 47 } 48 return ur 49 } 50 51 // ScaleLineSegment segment's size to length flexible in limit 52 func ScaleLineSegment[E constraints_.Number](segment Point[E], length E, limit Point[E]) Point[E] { 53 var swapped = segment.X > segment.Y 54 if swapped { // swap (X,Y) -> (Y,X) 55 segment.X, segment.Y = segment.Y, segment.X 56 limit.X, limit.Y = limit.Y, limit.X 57 } 58 59 dx := length - (segment.Y - segment.X) 60 segment.X -= E(math.Round(float64(dx) / 2.0)) 61 if segment.X < limit.X { 62 segment.X = limit.X 63 } 64 segment.Y = segment.X + length 65 if segment.Y > limit.Y { 66 segment.Y = limit.Y 67 segment.X = segment.Y - length 68 if segment.X < limit.X { 69 segment.X = limit.X 70 } 71 } 72 73 if swapped { 74 segment.X, segment.Y = segment.Y, segment.X 75 } 76 return segment 77 } 78 79 // ScaleRectangleBySize scale rect to size flexible in limit 80 func ScaleRectangleBySize[E constraints.Integer](rect Rectangle[E], size Point[E], limit Rectangle[E]) Rectangle[E] { 81 // padding in x direction 82 x := ScaleLineSegment(Pt(rect.Min.X, rect.Max.X), size.X, Pt(limit.Min.X, limit.Max.X)) 83 // padding in y direction 84 y := ScaleLineSegment(Pt(rect.Min.Y, rect.Max.Y), size.Y, Pt(limit.Min.Y, limit.Max.Y)) 85 86 return limit.Intersect(Rect(x.X, y.X, x.Y, y.Y)) 87 }