use per-axis padding

This commit is contained in:
Gavin Nishizawa 2023-02-10 16:19:19 -08:00
parent 93fa13ab0f
commit 94bf92a28b
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD
5 changed files with 20 additions and 15 deletions

View file

@ -863,6 +863,11 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
}
}
// to examine GetInsidePlacement
// padX, padY := s.GetDefaultPadding()
// innerTL := s.GetInsidePlacement(s.GetInnerBox().Width, s.GetInnerBox().Height, padX, padY)
// fmt.Fprint(writer, renderOval(&innerTL, 5, 5, "fill:red;"))
// Closes the class=shape
fmt.Fprint(writer, `</g>`)

View file

@ -47,7 +47,7 @@ type Shape interface {
GetInnerBox() *geo.Box
// placing a rectangle of the given size and padding inside the shape, return the position relative to the shape's TopLeft
GetInsidePlacement(width, height, padding float64) geo.Point
GetInsidePlacement(width, height, paddingX, paddingY float64) geo.Point
GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64)
GetDefaultPadding() (paddingX, paddingY float64)
@ -88,9 +88,9 @@ func (s baseShape) GetInnerBox() *geo.Box {
return s.Box
}
func (s baseShape) GetInsidePlacement(_, _, padding float64) geo.Point {
func (s baseShape) GetInsidePlacement(_, _, paddingX, paddingY float64) geo.Point {
innerTL := (*s.FullShape).GetInnerBox().TopLeft
return *geo.NewPoint(innerTL.X+padding/2, innerTL.Y+padding/2)
return *geo.NewPoint(innerTL.X+paddingX/2, innerTL.Y+paddingY/2)
}
// return the minimum shape dimensions needed to fit content (width x height)

View file

@ -25,7 +25,7 @@ func NewCircle(box *geo.Box) Shape {
func (s shapeCircle) GetInnerBox() *geo.Box {
width := s.Box.Width
height := s.Box.Height
insideTL := s.GetInsidePlacement(width, height, 0)
insideTL := s.GetInsidePlacement(width, height, 0, 0)
tl := s.Box.TopLeft.Copy()
width -= 2 * (insideTL.X - tl.X)
height -= 2 * (insideTL.Y - tl.Y)
@ -41,7 +41,7 @@ func (s shapeCircle) GetDimensionsToFit(width, height, paddingX, paddingY float6
return diameter, diameter
}
func (s shapeCircle) GetInsidePlacement(width, height, padding float64) geo.Point {
func (s shapeCircle) GetInsidePlacement(width, height, paddingX, paddingY float64) geo.Point {
return *geo.NewPoint(s.Box.TopLeft.X+math.Ceil(s.Box.Width/2-width/2), s.Box.TopLeft.Y+math.Ceil(s.Box.Height/2-height/2))
}

View file

@ -46,7 +46,7 @@ func NewCloud(box *geo.Box) Shape {
func (s shapeCloud) GetInnerBox() *geo.Box {
width := s.Box.Width
height := s.Box.Height
insideTL := s.GetInsidePlacement(width, height, 0)
insideTL := s.GetInsidePlacement(width, height, 0, 0)
aspectRatio := width / height
if aspectRatio > CLOUD_WIDE_ASPECT_BOUNDARY {
width *= CLOUD_WIDE_INNER_WIDTH
@ -75,17 +75,17 @@ func (s shapeCloud) GetDimensionsToFit(width, height, paddingX, paddingY float64
}
}
func (s shapeCloud) GetInsidePlacement(width, height, padding float64) geo.Point {
func (s shapeCloud) GetInsidePlacement(width, height, paddingX, paddingY float64) geo.Point {
r := s.Box
width += padding
height += padding
width += paddingX
height += paddingY
aspectRatio := width / height
if aspectRatio > CLOUD_WIDE_ASPECT_BOUNDARY {
return *geo.NewPoint(r.TopLeft.X+math.Ceil(r.Width*CLOUD_WIDE_INNER_X+padding/2), r.TopLeft.Y+math.Ceil(r.Height*CLOUD_WIDE_INNER_Y+padding/2))
return *geo.NewPoint(r.TopLeft.X+math.Ceil(r.Width*CLOUD_WIDE_INNER_X+paddingX/2), r.TopLeft.Y+math.Ceil(r.Height*CLOUD_WIDE_INNER_Y+paddingY/2))
} else if aspectRatio < CLOUD_TALL_ASPECT_BOUNDARY {
return *geo.NewPoint(r.TopLeft.X+math.Ceil(r.Width*CLOUD_TALL_INNER_X+padding/2), r.TopLeft.Y+math.Ceil(r.Height*CLOUD_TALL_INNER_Y+padding/2))
return *geo.NewPoint(r.TopLeft.X+math.Ceil(r.Width*CLOUD_TALL_INNER_X+paddingX/2), r.TopLeft.Y+math.Ceil(r.Height*CLOUD_TALL_INNER_Y+paddingY/2))
} else {
return *geo.NewPoint(r.TopLeft.X+math.Ceil(r.Width*CLOUD_SQUARE_INNER_X+padding/2), r.TopLeft.Y+math.Ceil(r.Height*CLOUD_SQUARE_INNER_Y+padding/2))
return *geo.NewPoint(r.TopLeft.X+math.Ceil(r.Width*CLOUD_SQUARE_INNER_X+paddingX/2), r.TopLeft.Y+math.Ceil(r.Height*CLOUD_SQUARE_INNER_Y+paddingY/2))
}
}

View file

@ -25,7 +25,7 @@ func NewOval(box *geo.Box) Shape {
func (s shapeOval) GetInnerBox() *geo.Box {
width := s.Box.Width
height := s.Box.Height
insideTL := s.GetInsidePlacement(width, height, 0)
insideTL := s.GetInsidePlacement(width, height, 0, 0)
tl := s.Box.TopLeft.Copy()
width -= 2 * (insideTL.X - tl.X)
height -= 2 * (insideTL.Y - tl.Y)
@ -41,7 +41,7 @@ func (s shapeOval) GetDimensionsToFit(width, height, paddingX, paddingY float64)
return math.Ceil(math.Sqrt2 * paddedWidth), math.Ceil(math.Sqrt2 * paddedHeight)
}
func (s shapeOval) GetInsidePlacement(width, height, padding float64) geo.Point {
func (s shapeOval) GetInsidePlacement(width, height, paddingX, paddingY float64) geo.Point {
// showing the top left arc of the ellipse (drawn with '*')
// ┌──────────────────* ┬
// │ * │ │ry
@ -60,7 +60,7 @@ func (s shapeOval) GetInsidePlacement(width, height, padding float64) geo.Point
// see https://math.stackexchange.com/questions/432902/how-to-get-the-radius-of-an-ellipse-at-a-specific-angle-by-knowing-its-semi-majo
r := rx * ry / math.Sqrt(math.Pow(rx*sin, 2)+math.Pow(ry*cos, 2))
// we want to offset r-padding/2 away from the center
return *geo.NewPoint(s.Box.TopLeft.X+math.Ceil(rx-cos*(r-padding/2)), s.Box.TopLeft.Y+math.Ceil(ry-sin*(r-padding/2)))
return *geo.NewPoint(s.Box.TopLeft.X+math.Ceil(rx-cos*(r-paddingX/2)), s.Box.TopLeft.Y+math.Ceil(ry-sin*(r-paddingY/2)))
}
func (s shapeOval) Perimeter() []geo.Intersectable {