...

Source file src/oss.terrastruct.com/d2/lib/geo/box.go

Documentation: oss.terrastruct.com/d2/lib/geo

     1  package geo
     2  
     3  import "fmt"
     4  
     5  type Box struct {
     6  	TopLeft *Point
     7  	Width   float64
     8  	Height  float64
     9  }
    10  
    11  func NewBox(tl *Point, width, height float64) *Box {
    12  	return &Box{
    13  		TopLeft: tl,
    14  		Width:   width,
    15  		Height:  height,
    16  	}
    17  }
    18  
    19  func (b *Box) Copy() *Box {
    20  	if b == nil {
    21  		return nil
    22  	}
    23  	return NewBox(b.TopLeft.Copy(), b.Width, b.Height)
    24  }
    25  
    26  func (b *Box) Center() *Point {
    27  	return NewPoint(b.TopLeft.X+b.Width/2, b.TopLeft.Y+b.Height/2)
    28  }
    29  
    30  // Intersects returns true if the segment comes within buffer of the box
    31  func (b *Box) Intersects(s Segment, buffer float64) bool {
    32  	tl := NewPoint(b.TopLeft.X-buffer, b.TopLeft.Y-buffer)
    33  	tr := NewPoint(tl.X+b.Width+buffer*2, tl.Y)
    34  	br := NewPoint(tr.X, tr.Y+b.Height+buffer*2)
    35  	bl := NewPoint(tl.X, br.Y)
    36  
    37  	if p := IntersectionPoint(s.Start, s.End, tl, tr); p != nil {
    38  		return true
    39  	}
    40  	if p := IntersectionPoint(s.Start, s.End, tr, br); p != nil {
    41  		return true
    42  	}
    43  	if p := IntersectionPoint(s.Start, s.End, br, bl); p != nil {
    44  		return true
    45  	}
    46  	if p := IntersectionPoint(s.Start, s.End, bl, tl); p != nil {
    47  		return true
    48  	}
    49  	return false
    50  }
    51  
    52  func (b *Box) Intersections(s Segment) []*Point {
    53  	pts := []*Point{}
    54  
    55  	tl := b.TopLeft
    56  	tr := NewPoint(tl.X+b.Width, tl.Y)
    57  	br := NewPoint(tr.X, tr.Y+b.Height)
    58  	bl := NewPoint(tl.X, br.Y)
    59  
    60  	if p := IntersectionPoint(s.Start, s.End, tl, tr); p != nil {
    61  		pts = append(pts, p)
    62  	}
    63  	if p := IntersectionPoint(s.Start, s.End, tr, br); p != nil {
    64  		pts = append(pts, p)
    65  	}
    66  	if p := IntersectionPoint(s.Start, s.End, br, bl); p != nil {
    67  		pts = append(pts, p)
    68  	}
    69  	if p := IntersectionPoint(s.Start, s.End, bl, tl); p != nil {
    70  		pts = append(pts, p)
    71  	}
    72  	return pts
    73  }
    74  
    75  func (b *Box) ToString() string {
    76  	if b == nil {
    77  		return ""
    78  	}
    79  	return fmt.Sprintf("{TopLeft: %s, Width: %.0f, Height: %.0f}", b.TopLeft.ToString(), b.Width, b.Height)
    80  }
    81  
    82  func (b *Box) Contains(p *Point) bool {
    83  	return !(p.X < b.TopLeft.X || b.TopLeft.X+b.Width < p.X ||
    84  		p.Y < b.TopLeft.Y || b.TopLeft.Y+b.Height < p.Y)
    85  }
    86  
    87  func (b1 Box) Overlaps(b2 Box) bool {
    88  	// https://silentmatt.com/rectangle-intersection/
    89  	return (b1.TopLeft.X < (b2.TopLeft.X + b2.Width)) && ((b1.TopLeft.X + b1.Width) > b2.TopLeft.X) &&
    90  		(b1.TopLeft.Y < (b2.TopLeft.Y + b2.Height)) && ((b1.TopLeft.Y + b1.Height) > b2.TopLeft.Y)
    91  }
    92  

View as plain text