...

Source file src/oss.terrastruct.com/d2/lib/shape/shape_person.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 shapePerson struct {
    12  	*baseShape
    13  }
    14  
    15  func NewPerson(box *geo.Box) Shape {
    16  	shape := shapePerson{
    17  		baseShape: &baseShape{
    18  			Type: PERSON_TYPE,
    19  			Box:  box,
    20  		},
    21  	}
    22  	shape.FullShape = go2.Pointer(Shape(shape))
    23  	return shape
    24  }
    25  
    26  const (
    27  	PERSON_AR_LIMIT = 1.5
    28  
    29  	personShoulderWidthFactor = 20.2 / 68.3
    30  )
    31  
    32  func (s shapePerson) GetInnerBox() *geo.Box {
    33  	width := s.Box.Width
    34  	tl := s.Box.TopLeft.Copy()
    35  	shoulderWidth := personShoulderWidthFactor * width
    36  	tl.X += shoulderWidth
    37  	width -= shoulderWidth * 2
    38  	return geo.NewBox(tl, width, s.Box.Height)
    39  }
    40  
    41  func personPath(box *geo.Box) *svg.SvgPathContext {
    42  	pc := svg.NewSVGPathContext(box.TopLeft, box.Width/68.3, box.Height/77.4)
    43  
    44  	// Bottom side
    45  	pc.StartAt(pc.Absolute(68.3, 77.4))
    46  	pc.H(false, 0)
    47  	pc.V(true, -1.1)
    48  	pc.C(true, 0, -13.2, 7.5, -25.1, 19.3, -30.8)
    49  	pc.C(false, 12.8, 40.9, 8.9, 33.4, 8.9, 25.2)
    50  	pc.C(false, 8.9, 11.3, 20.2, 0, 34.1, 0)
    51  
    52  	// TODO: implement s command with mirroring last control point
    53  	// s 			25.2,11.3, 	25.2,25.2
    54  	// mirroring last control point (20.2,0) -> (34.1,0) = relative(13.9,0)
    55  	pc.C(true, 13.9, 0, 25.2, 11.3, 25.2, 25.2)
    56  
    57  	pc.C(true, 0, 8.2, -3.8, 15.6, -10.4, 20.4)
    58  	pc.C(true, 11.8, 5.7, 19.3, 17.6, 19.3, 30.8)
    59  	pc.V(true, 1)
    60  	pc.H(false, 68.3)
    61  	pc.Z()
    62  	return pc
    63  }
    64  
    65  func (s shapePerson) Perimeter() []geo.Intersectable {
    66  	return personPath(s.Box).Path
    67  
    68  }
    69  
    70  func (s shapePerson) GetSVGPathData() []string {
    71  	return []string{
    72  		personPath(s.Box).PathData(),
    73  	}
    74  }
    75  
    76  func (s shapePerson) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
    77  	totalWidth := width + paddingX
    78  	// see shapePackage
    79  	shoulderWidth := totalWidth * personShoulderWidthFactor / (1 - 2*personShoulderWidthFactor)
    80  	totalWidth += 2 * shoulderWidth
    81  	totalHeight := height + paddingY
    82  
    83  	// prevent the shape's aspect ratio from becoming too extreme
    84  	totalWidth, totalHeight = LimitAR(totalWidth, totalHeight, PERSON_AR_LIMIT)
    85  	return math.Ceil(totalWidth), math.Ceil(totalHeight)
    86  }
    87  
    88  func (s shapePerson) GetDefaultPadding() (paddingX, paddingY float64) {
    89  	return 10, defaultPadding
    90  }
    91  

View as plain text