diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go index 91cc687a8..a86e38960 100644 --- a/d2renderers/d2svg/d2svg.go +++ b/d2renderers/d2svg/d2svg.go @@ -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, ``) diff --git a/lib/shape/shape.go b/lib/shape/shape.go index 52784ddd7..d3dc97114 100644 --- a/lib/shape/shape.go +++ b/lib/shape/shape.go @@ -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) diff --git a/lib/shape/shape_circle.go b/lib/shape/shape_circle.go index 254b23aff..72526eecb 100644 --- a/lib/shape/shape_circle.go +++ b/lib/shape/shape_circle.go @@ -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)) } diff --git a/lib/shape/shape_cloud.go b/lib/shape/shape_cloud.go index 98925db75..656003368 100644 --- a/lib/shape/shape_cloud.go +++ b/lib/shape/shape_cloud.go @@ -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)) } } diff --git a/lib/shape/shape_oval.go b/lib/shape/shape_oval.go index 5a8ef5a59..9e75242eb 100644 --- a/lib/shape/shape_oval.go +++ b/lib/shape/shape_oval.go @@ -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 {