...

Source file src/oss.terrastruct.com/d2/lib/shape/shape_package.go

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

     1  package shape
     2  
     3  import (
     4  	"math"
     5  
     6  	"oss.terrastruct.com/d2/lib/geo"
     7  	"oss.terrastruct.com/d2/lib/svg"
     8  	"oss.terrastruct.com/util-go/go2"
     9  )
    10  
    11  type shapePackage struct {
    12  	*baseShape
    13  }
    14  
    15  const (
    16  	packageTopMinHeight     = 34.
    17  	packageTopMaxHeight     = 55.
    18  	packageTopMinWidth      = 50.
    19  	packageTopMaxWidth      = 150.
    20  	packageHorizontalScalar = 0.5
    21  	packageVerticalScalar   = 0.2
    22  )
    23  
    24  func NewPackage(box *geo.Box) Shape {
    25  	shape := shapePackage{
    26  		baseShape: &baseShape{
    27  			Type: PACKAGE_TYPE,
    28  			Box:  box,
    29  		},
    30  	}
    31  	shape.FullShape = go2.Pointer(Shape(shape))
    32  	return shape
    33  }
    34  
    35  func (s shapePackage) GetInnerBox() *geo.Box {
    36  	tl := s.Box.TopLeft.Copy()
    37  	height := s.Box.Height
    38  
    39  	_, topHeight := getTopDimensions(s.Box)
    40  	tl.Y += topHeight
    41  	height -= topHeight
    42  	return geo.NewBox(tl, s.Box.Width, height)
    43  }
    44  
    45  func getTopDimensions(box *geo.Box) (width, height float64) {
    46  	width = box.Width * packageHorizontalScalar
    47  	if box.Width >= 2*packageTopMinWidth {
    48  		width = math.Min(packageTopMaxWidth, math.Max(packageTopMinWidth, width))
    49  	}
    50  	height = math.Min(packageTopMaxHeight, box.Height*packageVerticalScalar)
    51  	return width, height
    52  }
    53  
    54  func packagePath(box *geo.Box) *svg.SvgPathContext {
    55  	topWidth, topHeight := getTopDimensions(box)
    56  
    57  	pc := svg.NewSVGPathContext(box.TopLeft, 1, 1)
    58  	pc.StartAt(pc.Absolute(0, 0))
    59  	pc.L(false, topWidth, 0)
    60  	pc.L(false, topWidth, topHeight)
    61  	pc.L(false, box.Width, topHeight)
    62  	pc.L(false, box.Width, box.Height)
    63  	pc.L(false, 0, box.Height)
    64  	pc.Z()
    65  	return pc
    66  }
    67  
    68  func (s shapePackage) Perimeter() []geo.Intersectable {
    69  	return packagePath(s.Box).Path
    70  }
    71  
    72  func (s shapePackage) GetSVGPathData() []string {
    73  	return []string{
    74  		packagePath(s.Box).PathData(),
    75  	}
    76  }
    77  
    78  func (s shapePackage) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
    79  	innerHeight := height + paddingY
    80  	// We want to compute what the topHeight will be to add to inner height;
    81  	// topHeight=(verticalScalar * totalHeight) and totalHeight=(topHeight + innerHeight)
    82  	// so solving for topHeight we get: topHeight=innerHeight * (verticalScalar/(1-verticalScalar))
    83  	topHeight := innerHeight * packageVerticalScalar / (1. - packageVerticalScalar)
    84  	totalHeight := innerHeight + math.Min(topHeight, packageTopMaxHeight)
    85  
    86  	return math.Ceil(width + paddingX), math.Ceil(totalHeight)
    87  }
    88  
    89  func (s shapePackage) GetDefaultPadding() (paddingX, paddingY float64) {
    90  	return defaultPadding, .8 * defaultPadding
    91  }
    92  

View as plain text