github.com/pavlo67/common@v0.5.3/common/mathlib/plane/rectangles.go (about)

     1  package plane
     2  
     3  type RectangleFixed [2]Point2
     4  
     5  //	func RectangleAround(pts []Point2) *RectangleFixed {
     6  //		if len(pts) < 1 {
     7  //			return nil
     8  //		}
     9  //
    10  //		minX, maxX, minY, maxY := pts[0].X, pts[0].X, pts[0].Y, pts[0].Y
    11  //
    12  //		for _, p := range pts[1:] {
    13  //			if p.X <= minX {
    14  //				minX = p.X
    15  //			} else if p.X > maxX {
    16  //				maxX = p.X
    17  //			}
    18  //			if p.Y <= minY {
    19  //				minY = p.Y
    20  //			} else if p.Y > maxY {
    21  //				maxY = p.Y
    22  //			}
    23  //		}
    24  //
    25  //		return &RectangleFixed{Point2{minX, minY}, Point2{maxX, maxY}}
    26  //	}
    27  func RectangleAround(pts ...Point2) RectangleFixed {
    28  	if len(pts) < 1 {
    29  		return RectangleFixed{}
    30  	}
    31  
    32  	minX, maxX, minY, maxY := pts[0].X, pts[0].X, pts[0].Y, pts[0].Y
    33  
    34  	for _, p := range pts[1:] {
    35  		if p.X <= minX {
    36  			minX = p.X
    37  		} else if p.X > maxX {
    38  			maxX = p.X
    39  		}
    40  		if p.Y <= minY {
    41  			minY = p.Y
    42  		} else if p.Y > maxY {
    43  			maxY = p.Y
    44  		}
    45  	}
    46  
    47  	return RectangleFixed{Point2{minX, minY}, Point2{maxX, maxY}}
    48  }
    49  
    50  func (rectFixed RectangleFixed) Contains(p2 Point2) bool {
    51  	minX, maxX, minY, maxY := rectFixed[0].X, rectFixed[1].X, rectFixed[0].Y, rectFixed[1].Y
    52  	if minX > maxX {
    53  		minX, maxX = maxX, minX
    54  	}
    55  	if minY > maxY {
    56  		minY, maxY = maxY, minY
    57  	}
    58  
    59  	return p2.X >= minX && p2.X <= maxX && p2.Y >= minY && p2.Y <= maxY
    60  }
    61  
    62  type Rectangle struct {
    63  	Position             // of the center
    64  	HalfSideX, HalfSideY float64
    65  }
    66  
    67  func (rect Rectangle) Sides() [2]Segment {
    68  
    69  	p00 := Point2{rect.HalfSideX, rect.HalfSideY}.RotateByAngle(rect.XToYAngle)
    70  	p01 := Point2{-rect.HalfSideX, rect.HalfSideY}.RotateByAngle(rect.XToYAngle)
    71  
    72  	return [2]Segment{{rect.Point2.Add(p00), rect.Point2.Add(p01)}, {rect.Point2.Sub(p00), rect.Point2.Sub(p01)}}
    73  }
    74  
    75  func (rect Rectangle) Contains(p2 Point2) bool {
    76  	p2Rotated := p2.RotateAround(rect.Point2, -rect.XToYAngle)
    77  	return p2Rotated.X >= rect.Point2.X-rect.HalfSideX && p2Rotated.X <= rect.Point2.X+rect.HalfSideX &&
    78  		p2Rotated.Y >= rect.Point2.Y-rect.HalfSideY && p2Rotated.Y <= rect.Point2.Y+rect.HalfSideY
    79  }
    80  
    81  func (rect Rectangle) Outer(margin float64) Rectangle {
    82  	return Rectangle{
    83  		Position:  rect.Position,
    84  		HalfSideX: rect.HalfSideX + margin,
    85  		HalfSideY: rect.HalfSideY + margin,
    86  	}
    87  }
    88  
    89  //func (rect Rectangle) Intersection(pCh PolyChain) PolyChain {
    90  //
    91  //	log.Fatal("on Rectangle.Intersects()")
    92  //
    93  //	//for _, p := range pCh {
    94  //	//	p2Rot := RotateByAngle(p, -rect.XToYAngleFromOy)
    95  //	//	if p2Rot.XT >= rect.Min.XT && p2Rot.XT <= rect.MaxIn.XT && p2Rot.YT >= rect.Min.YT && p2Rot.YT <= rect.MaxIn.YT {
    96  //	//		return true
    97  //	//	}
    98  //	//}
    99  //	return nil
   100  //}
   101  //
   102  //func (rect Rectangle) IntersectionArea(rect1 Rectangle) float64 {
   103  //
   104  //	log.Fatal("on Rectangle.IntersectionArea()")
   105  //
   106  //	return 0
   107  //}
   108  
   109  func (rect Rectangle) Points() (p00, p01, p10, p11 Point2) {
   110  	if rect.HalfSideX == 0 && rect.HalfSideY == 0 {
   111  		return rect.Point2, rect.Point2, rect.Point2, rect.Point2
   112  	}
   113  
   114  	p00Fixed, p01Fixed := Point2{-rect.HalfSideX, -rect.HalfSideY}, Point2{-rect.HalfSideX, rect.HalfSideY}
   115  	p00_, p01_ := p00Fixed.RotateByAngle(rect.XToYAngle), p01Fixed.RotateByAngle(rect.XToYAngle)
   116  
   117  	return Point2{p00_.X + rect.Point2.X, p00_.Y + rect.Point2.Y},
   118  		Point2{p01_.X + rect.Point2.X, p01_.Y + rect.Point2.Y},
   119  		Point2{-p01_.X + rect.Point2.X, -p01_.Y + rect.Point2.Y},
   120  		Point2{-p00_.X + rect.Point2.X, -p00_.Y + rect.Point2.Y}
   121  }
   122  
   123  func (rect Rectangle) OuterFixed(margin float64) RectangleFixed {
   124  	p00, p01, p10, p11 := rect.Points()
   125  
   126  	minX, maxX, minY, maxY := p11.X, p11.X, p11.Y, p11.Y
   127  	for _, p := range []Point2{p00, p01, p10} {
   128  		if p.X >= maxX {
   129  			maxX = p.X
   130  		} else if p.X < minX {
   131  			minX = p.X
   132  		}
   133  		if p.Y >= maxY {
   134  			maxY = p.Y
   135  		} else if p.Y < minY {
   136  			minY = p.Y
   137  		}
   138  	}
   139  
   140  	return RectangleFixed{Point2{minX - margin, minY - margin}, Point2{maxX + margin, maxY + margin}}
   141  }