github.com/searKing/golang/go@v1.2.117/image/geom.go (about) 1 // Copyright 2022 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 "image" 9 "math" 10 ) 11 12 // UnionPoints returns the smallest rectangle that contains all points. 13 // an empty rectangle is a empty set, Not a point 14 func UnionPoints(pts ...image.Point) image.Rectangle { 15 if len(pts) == 0 { 16 return image.Rectangle{} 17 } 18 19 r := image.Rectangle{ 20 Min: pts[0], 21 Max: pts[0], 22 } 23 for _, p := range pts[1:] { 24 if p.X < r.Min.X { 25 r.Min.X = p.X 26 } 27 if p.Y < r.Min.Y { 28 r.Min.Y = p.Y 29 } 30 if p.X > r.Max.X { 31 r.Max.X = p.X 32 } 33 if p.Y > r.Max.Y { 34 r.Max.Y = p.Y 35 } 36 } 37 return r 38 } 39 40 // UnionRectangles returns the smallest rectangle that contains all rectangles, empty rectangles excluded. 41 func UnionRectangles(rs ...image.Rectangle) image.Rectangle { 42 var ur image.Rectangle 43 for _, r := range rs { 44 ur = ur.Union(r) 45 } 46 return ur 47 } 48 49 // ScaleLineSegment segment's size to length flexible in limit 50 func ScaleLineSegment(segment image.Point, length int, limit image.Point) image.Point { 51 var swapped = segment.X > segment.Y 52 if swapped { // swap (X,Y) -> (Y,X) 53 segment.X, segment.Y = segment.Y, segment.X 54 limit.X, limit.Y = limit.Y, limit.X 55 } 56 57 dx := length - (segment.Y - segment.X) 58 segment.X -= int(math.Round(float64(dx) / 2.0)) 59 if segment.X < limit.X { 60 segment.X = limit.X 61 } 62 segment.Y = segment.X + length 63 if segment.Y > limit.Y { 64 segment.Y = limit.Y 65 segment.X = segment.Y - length 66 if segment.X < limit.X { 67 segment.X = limit.X 68 } 69 } 70 71 if swapped { 72 segment.X, segment.Y = segment.Y, segment.X 73 } 74 return segment 75 } 76 77 // ScaleRectangleBySize scale rect to size flexible in limit 78 func ScaleRectangleBySize(rect image.Rectangle, size image.Point, limit image.Rectangle) image.Rectangle { 79 // padding in x direction 80 x := ScaleLineSegment(image.Pt(rect.Min.X, rect.Max.X), size.X, image.Pt(limit.Min.X, limit.Max.X)) 81 // padding in y direction 82 y := ScaleLineSegment(image.Pt(rect.Min.Y, rect.Max.Y), size.Y, image.Pt(limit.Min.Y, limit.Max.Y)) 83 84 return limit.Intersect(image.Rect(x.X, y.X, x.Y, y.Y)) 85 }