From 6b65665b6126c65f0e6f1f0519b6759a24db3c99 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Thu, 9 Feb 2023 19:42:30 -0800 Subject: [PATCH 1/3] fix GetInsidePlacement inconsistencies --- lib/shape/shape.go | 3 ++- lib/shape/shape_oval.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/shape/shape.go b/lib/shape/shape.go index db74424b3..923cb1215 100644 --- a/lib/shape/shape.go +++ b/lib/shape/shape.go @@ -87,7 +87,8 @@ func (s baseShape) GetInnerBox() *geo.Box { } func (s baseShape) GetInsidePlacement(_, _, padding float64) geo.Point { - return *geo.NewPoint(s.Box.TopLeft.X+padding, s.Box.TopLeft.Y+padding) + innerTL := s.GetInnerBox().TopLeft + return *geo.NewPoint(innerTL.X+padding, innerTL.Y+padding) } // return the minimum shape dimensions needed to fit content (width x height) diff --git a/lib/shape/shape_oval.go b/lib/shape/shape_oval.go index 77ee82fc7..90e897fe8 100644 --- a/lib/shape/shape_oval.go +++ b/lib/shape/shape_oval.go @@ -56,8 +56,8 @@ func (s shapeOval) GetInsidePlacement(width, height, padding float64) geo.Point // r is the ellipse radius on the line between node.TopLeft and the ellipse center // 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 away from the center - return *geo.NewPoint(s.Box.TopLeft.X+math.Ceil(rx-cos*(r-padding)), s.Box.TopLeft.Y+math.Ceil(ry-sin*(r-padding))) + // 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))) } func (s shapeOval) Perimeter() []geo.Intersectable { From 93fa13ab0f2e85534c4c3f17de1bd16e12adac91 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Fri, 10 Feb 2023 11:03:07 -0800 Subject: [PATCH 2/3] add FullShape to use shape's InnerBox for placement --- lib/shape/shape.go | 14 +++++++++----- lib/shape/shape_callout.go | 5 ++++- lib/shape/shape_circle.go | 5 ++++- lib/shape/shape_class.go | 5 ++++- lib/shape/shape_cloud.go | 5 ++++- lib/shape/shape_code.go | 5 ++++- lib/shape/shape_cylinder.go | 5 ++++- lib/shape/shape_diamond.go | 5 ++++- lib/shape/shape_document.go | 5 ++++- lib/shape/shape_hexagon.go | 5 ++++- lib/shape/shape_image.go | 5 ++++- lib/shape/shape_oval.go | 5 ++++- lib/shape/shape_package.go | 5 ++++- lib/shape/shape_page.go | 5 ++++- lib/shape/shape_parallelogram.go | 5 ++++- lib/shape/shape_person.go | 5 ++++- lib/shape/shape_queue.go | 5 ++++- lib/shape/shape_real_square.go | 5 ++++- lib/shape/shape_square.go | 5 ++++- lib/shape/shape_step.go | 5 ++++- lib/shape/shape_stored_data.go | 5 ++++- lib/shape/shape_table.go | 5 ++++- lib/shape/shape_text.go | 5 ++++- 23 files changed, 97 insertions(+), 27 deletions(-) diff --git a/lib/shape/shape.go b/lib/shape/shape.go index 923cb1215..52784ddd7 100644 --- a/lib/shape/shape.go +++ b/lib/shape/shape.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) const ( @@ -58,8 +59,9 @@ type Shape interface { } type baseShape struct { - Type string - Box *geo.Box + Type string + Box *geo.Box + FullShape *Shape } func (s baseShape) Is(shapeType string) bool { @@ -87,8 +89,8 @@ func (s baseShape) GetInnerBox() *geo.Box { } func (s baseShape) GetInsidePlacement(_, _, padding float64) geo.Point { - innerTL := s.GetInnerBox().TopLeft - return *geo.NewPoint(innerTL.X+padding, innerTL.Y+padding) + innerTL := (*s.FullShape).GetInnerBox().TopLeft + return *geo.NewPoint(innerTL.X+padding/2, innerTL.Y+padding/2) } // return the minimum shape dimensions needed to fit content (width x height) @@ -157,12 +159,14 @@ func NewShape(shapeType string, box *geo.Box) Shape { return NewText(box) default: - return shapeSquare{ + shape := shapeSquare{ baseShape: &baseShape{ Type: shapeType, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } } diff --git a/lib/shape/shape_callout.go b/lib/shape/shape_callout.go index 36cd23779..4c28e04b9 100644 --- a/lib/shape/shape_callout.go +++ b/lib/shape/shape_callout.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeCallout struct { @@ -17,12 +18,14 @@ const ( ) func NewCallout(box *geo.Box) Shape { - return shapeCallout{ + shape := shapeCallout{ baseShape: &baseShape{ Type: CALLOUT_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func getTipWidth(box *geo.Box) float64 { diff --git a/lib/shape/shape_circle.go b/lib/shape/shape_circle.go index 57cb8937f..254b23aff 100644 --- a/lib/shape/shape_circle.go +++ b/lib/shape/shape_circle.go @@ -4,6 +4,7 @@ import ( "math" "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) type shapeCircle struct { @@ -11,12 +12,14 @@ type shapeCircle struct { } func NewCircle(box *geo.Box) Shape { - return shapeCircle{ + shape := shapeCircle{ baseShape: &baseShape{ Type: CIRCLE_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeCircle) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_class.go b/lib/shape/shape_class.go index 3f7f67a12..617e83eaa 100644 --- a/lib/shape/shape_class.go +++ b/lib/shape/shape_class.go @@ -2,6 +2,7 @@ package shape import ( "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) // Class is basically a rectangle @@ -10,7 +11,7 @@ type shapeClass struct { } func NewClass(box *geo.Box) Shape { - return shapeClass{ + shape := shapeClass{ shapeSquare{ baseShape: &baseShape{ Type: CLASS_TYPE, @@ -18,6 +19,8 @@ func NewClass(box *geo.Box) Shape { }, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeClass) GetDefaultPadding() (paddingX, paddingY float64) { diff --git a/lib/shape/shape_cloud.go b/lib/shape/shape_cloud.go index 5e3b19cb7..98925db75 100644 --- a/lib/shape/shape_cloud.go +++ b/lib/shape/shape_cloud.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) // The percentage values of the cloud's wide inner box @@ -32,12 +33,14 @@ type shapeCloud struct { } func NewCloud(box *geo.Box) Shape { - return shapeCloud{ + shape := shapeCloud{ baseShape: &baseShape{ Type: CLOUD_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeCloud) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_code.go b/lib/shape/shape_code.go index 2c0f4b1e1..0274ca6c4 100644 --- a/lib/shape/shape_code.go +++ b/lib/shape/shape_code.go @@ -2,6 +2,7 @@ package shape import ( "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) type shapeCode struct { @@ -9,7 +10,7 @@ type shapeCode struct { } func NewCode(box *geo.Box) Shape { - return shapeCode{ + shape := shapeCode{ shapeSquare: shapeSquare{ baseShape: &baseShape{ Type: CODE_TYPE, @@ -17,6 +18,8 @@ func NewCode(box *geo.Box) Shape { }, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeCode) GetDefaultPadding() (paddingX, paddingY float64) { diff --git a/lib/shape/shape_cylinder.go b/lib/shape/shape_cylinder.go index c0dcc6b9a..d879484f9 100644 --- a/lib/shape/shape_cylinder.go +++ b/lib/shape/shape_cylinder.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeCylinder struct { @@ -16,12 +17,14 @@ const ( ) func NewCylinder(box *geo.Box) Shape { - return shapeCylinder{ + shape := shapeCylinder{ baseShape: &baseShape{ Type: CYLINDER_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func getArcHeight(box *geo.Box) float64 { diff --git a/lib/shape/shape_diamond.go b/lib/shape/shape_diamond.go index a0a456cb6..b97308bdf 100644 --- a/lib/shape/shape_diamond.go +++ b/lib/shape/shape_diamond.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeDiamond struct { @@ -12,12 +13,14 @@ type shapeDiamond struct { } func NewDiamond(box *geo.Box) Shape { - return shapeDiamond{ + shape := shapeDiamond{ baseShape: &baseShape{ Type: DIAMOND_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeDiamond) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_document.go b/lib/shape/shape_document.go index e3238ea3c..9649822cf 100644 --- a/lib/shape/shape_document.go +++ b/lib/shape/shape_document.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeDocument struct { @@ -19,12 +20,14 @@ const ( ) func NewDocument(box *geo.Box) Shape { - return shapeDocument{ + shape := shapeDocument{ baseShape: &baseShape{ Type: DOCUMENT_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeDocument) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_hexagon.go b/lib/shape/shape_hexagon.go index 3d4492053..964d31866 100644 --- a/lib/shape/shape_hexagon.go +++ b/lib/shape/shape_hexagon.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeHexagon struct { @@ -12,12 +13,14 @@ type shapeHexagon struct { } func NewHexagon(box *geo.Box) Shape { - return shapeHexagon{ + shape := shapeHexagon{ baseShape: &baseShape{ Type: HEXAGON_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeHexagon) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_image.go b/lib/shape/shape_image.go index ae3923298..9b232a0d4 100644 --- a/lib/shape/shape_image.go +++ b/lib/shape/shape_image.go @@ -2,6 +2,7 @@ package shape import ( "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) type shapeImage struct { @@ -9,12 +10,14 @@ type shapeImage struct { } func NewImage(box *geo.Box) Shape { - return shapeImage{ + shape := shapeImage{ baseShape: &baseShape{ Type: IMAGE_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeImage) IsRectangular() bool { diff --git a/lib/shape/shape_oval.go b/lib/shape/shape_oval.go index 90e897fe8..5a8ef5a59 100644 --- a/lib/shape/shape_oval.go +++ b/lib/shape/shape_oval.go @@ -4,6 +4,7 @@ import ( "math" "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) type shapeOval struct { @@ -11,12 +12,14 @@ type shapeOval struct { } func NewOval(box *geo.Box) Shape { - return shapeOval{ + shape := shapeOval{ baseShape: &baseShape{ Type: OVAL_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeOval) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_package.go b/lib/shape/shape_package.go index 39da973c8..d9bcfbec2 100644 --- a/lib/shape/shape_package.go +++ b/lib/shape/shape_package.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapePackage struct { @@ -21,12 +22,14 @@ const ( ) func NewPackage(box *geo.Box) Shape { - return shapePackage{ + shape := shapePackage{ baseShape: &baseShape{ Type: PACKAGE_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapePackage) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_page.go b/lib/shape/shape_page.go index 5a836c4ab..919bc8b63 100644 --- a/lib/shape/shape_page.go +++ b/lib/shape/shape_page.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapePage struct { @@ -18,12 +19,14 @@ const ( ) func NewPage(box *geo.Box) Shape { - return shapePage{ + shape := shapePage{ baseShape: &baseShape{ Type: PAGE_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapePage) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_parallelogram.go b/lib/shape/shape_parallelogram.go index 90c1dc41f..5ffb09b38 100644 --- a/lib/shape/shape_parallelogram.go +++ b/lib/shape/shape_parallelogram.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeParallelogram struct { @@ -14,12 +15,14 @@ type shapeParallelogram struct { const parallelWedgeWidth = 26. func NewParallelogram(box *geo.Box) Shape { - return shapeParallelogram{ + shape := shapeParallelogram{ baseShape: &baseShape{ Type: PARALLELOGRAM_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeParallelogram) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_person.go b/lib/shape/shape_person.go index c43fea29e..e6452ab64 100644 --- a/lib/shape/shape_person.go +++ b/lib/shape/shape_person.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapePerson struct { @@ -12,12 +13,14 @@ type shapePerson struct { } func NewPerson(box *geo.Box) Shape { - return shapePerson{ + shape := shapePerson{ baseShape: &baseShape{ Type: PERSON_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } const ( diff --git a/lib/shape/shape_queue.go b/lib/shape/shape_queue.go index 10a21ff0d..3438054af 100644 --- a/lib/shape/shape_queue.go +++ b/lib/shape/shape_queue.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeQueue struct { @@ -12,12 +13,14 @@ type shapeQueue struct { } func NewQueue(box *geo.Box) Shape { - return shapeQueue{ + shape := shapeQueue{ baseShape: &baseShape{ Type: QUEUE_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func getArcWidth(box *geo.Box) float64 { diff --git a/lib/shape/shape_real_square.go b/lib/shape/shape_real_square.go index 3948d7d7a..5da464f1e 100644 --- a/lib/shape/shape_real_square.go +++ b/lib/shape/shape_real_square.go @@ -4,6 +4,7 @@ import ( "math" "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) type shapeRealSquare struct { @@ -11,12 +12,14 @@ type shapeRealSquare struct { } func NewRealSquare(box *geo.Box) Shape { - return shapeRealSquare{ + shape := shapeRealSquare{ baseShape: &baseShape{ Type: REAL_SQUARE_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeRealSquare) AspectRatio1() bool { diff --git a/lib/shape/shape_square.go b/lib/shape/shape_square.go index ceb811e4c..5c5954d18 100644 --- a/lib/shape/shape_square.go +++ b/lib/shape/shape_square.go @@ -2,6 +2,7 @@ package shape import ( "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) type shapeSquare struct { @@ -9,12 +10,14 @@ type shapeSquare struct { } func NewSquare(box *geo.Box) Shape { - return shapeSquare{ + shape := shapeSquare{ baseShape: &baseShape{ Type: SQUARE_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeSquare) IsRectangular() bool { diff --git a/lib/shape/shape_step.go b/lib/shape/shape_step.go index c7b9dc0e0..cdc471725 100644 --- a/lib/shape/shape_step.go +++ b/lib/shape/shape_step.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeStep struct { @@ -12,12 +13,14 @@ type shapeStep struct { } func NewStep(box *geo.Box) Shape { - return shapeStep{ + shape := shapeStep{ baseShape: &baseShape{ Type: STEP_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } const STEP_WEDGE_WIDTH = 35.0 diff --git a/lib/shape/shape_stored_data.go b/lib/shape/shape_stored_data.go index 69e127e7e..b059c183d 100644 --- a/lib/shape/shape_stored_data.go +++ b/lib/shape/shape_stored_data.go @@ -5,6 +5,7 @@ import ( "oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/svg" + "oss.terrastruct.com/util-go/go2" ) type shapeStoredData struct { @@ -14,12 +15,14 @@ type shapeStoredData struct { const storedDataWedgeWidth = 15. func NewStoredData(box *geo.Box) Shape { - return shapeStoredData{ + shape := shapeStoredData{ baseShape: &baseShape{ Type: STORED_DATA_TYPE, Box: box, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeStoredData) GetInnerBox() *geo.Box { diff --git a/lib/shape/shape_table.go b/lib/shape/shape_table.go index 6d66b9a43..052ae7937 100644 --- a/lib/shape/shape_table.go +++ b/lib/shape/shape_table.go @@ -2,6 +2,7 @@ package shape import ( "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) // Table is basically a rectangle @@ -10,7 +11,7 @@ type shapeTable struct { } func NewTable(box *geo.Box) Shape { - return shapeTable{ + shape := shapeTable{ shapeSquare{ baseShape: &baseShape{ Type: TABLE_TYPE, @@ -18,6 +19,8 @@ func NewTable(box *geo.Box) Shape { }, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeTable) GetDefaultPadding() (paddingX, paddingY float64) { diff --git a/lib/shape/shape_text.go b/lib/shape/shape_text.go index 078609e0b..3ae2c986e 100644 --- a/lib/shape/shape_text.go +++ b/lib/shape/shape_text.go @@ -2,6 +2,7 @@ package shape import ( "oss.terrastruct.com/d2/lib/geo" + "oss.terrastruct.com/util-go/go2" ) // Text is basically a rectangle @@ -10,7 +11,7 @@ type shapeText struct { } func NewText(box *geo.Box) Shape { - return shapeText{ + shape := shapeText{ shapeSquare: shapeSquare{ baseShape: &baseShape{ Type: TEXT_TYPE, @@ -18,6 +19,8 @@ func NewText(box *geo.Box) Shape { }, }, } + shape.FullShape = go2.Pointer(Shape(shape)) + return shape } func (s shapeText) GetDefaultPadding() (paddingX, paddingY float64) { From 94bf92a28bc8ad613b79f72337943a1db31e75c1 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Fri, 10 Feb 2023 16:19:19 -0800 Subject: [PATCH 3/3] use per-axis padding --- d2renderers/d2svg/d2svg.go | 5 +++++ lib/shape/shape.go | 6 +++--- lib/shape/shape_circle.go | 4 ++-- lib/shape/shape_cloud.go | 14 +++++++------- lib/shape/shape_oval.go | 6 +++--- 5 files changed, 20 insertions(+), 15 deletions(-) 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 {