use paddingX and paddingY in GetDimensionsToFit

This commit is contained in:
Gavin Nishizawa 2023-01-23 10:32:12 -08:00
parent b76d43536d
commit 0311a3f7d7
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD
23 changed files with 98 additions and 78 deletions

View file

@ -23,7 +23,7 @@ import (
)
const INNER_LABEL_PADDING int = 5
const DEFAULT_SHAPE_PADDING = 100.
const DEFAULT_SHAPE_SIZE = 100.
// TODO: Refactor with a light abstract layer on top of AST implementing scenarios,
// variables, imports, substitutions and then a final set of structures representing
@ -827,21 +827,6 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
return &dims, nil
}
func (obj *Object) GetPadding() (x, y float64) {
switch strings.ToLower(obj.Attributes.Shape.Value) {
case d2target.ShapeImage,
d2target.ShapeSQLTable,
d2target.ShapeText,
d2target.ShapeCode:
return 0., 0.
case d2target.ShapeClass:
// TODO fix class row width measurements (see SQL table)
return 100., 0.
default:
return DEFAULT_SHAPE_PADDING, DEFAULT_SHAPE_PADDING
}
}
type Edge struct {
Index int `json:"index"`
@ -1107,8 +1092,8 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
obj.Attributes.Shape.Value != d2target.ShapeImage &&
obj.Attributes.Shape.Value != d2target.ShapeSQLTable &&
obj.Attributes.Shape.Value != d2target.ShapeClass {
obj.Width = DEFAULT_SHAPE_PADDING
obj.Height = DEFAULT_SHAPE_PADDING
obj.Width = DEFAULT_SHAPE_SIZE
obj.Height = DEFAULT_SHAPE_SIZE
if desiredWidth != 0 {
obj.Width = float64(desiredWidth)
}
@ -1149,10 +1134,13 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
obj.Width = float64(go2.Max(defaultDims.Width, desiredWidth))
obj.Height = float64(go2.Max(defaultDims.Height, desiredHeight))
paddingX, paddingY := obj.GetPadding()
shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[dslShape]
contentBox := geo.NewBox(geo.NewPoint(0, 0), float64(defaultDims.Width), float64(defaultDims.Height))
s := shape.NewShape(shapeType, contentBox)
switch dslShape {
case d2target.ShapeSquare, d2target.ShapeCircle:
paddingX, paddingY := s.GetDefaultPadding()
if s.AspectRatio1() {
if desiredWidth != 0 || desiredHeight != 0 {
paddingX = 0.
paddingY = 0.
@ -1161,8 +1149,7 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
sideLength := math.Max(obj.Width+paddingX, obj.Height+paddingY)
obj.Width = sideLength
obj.Height = sideLength
default:
} else {
if desiredWidth == 0 {
obj.Width += float64(paddingX)
}
@ -1170,12 +1157,12 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
obj.Height += float64(paddingY)
}
}
contentBox := geo.NewBox(geo.NewPoint(0, 0), float64(defaultDims.Width), float64(defaultDims.Height))
shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[dslShape]
s := shape.NewShape(shapeType, contentBox)
newWidth, newHeight := s.GetDimensionsToFit(contentBox.Width, contentBox.Height, paddingX/2)
obj.Width = newWidth
obj.Height = newHeight
if desiredWidth == 0 && desiredHeight == 0 {
newWidth, newHeight := s.GetDimensionsToFit(contentBox.Width, contentBox.Height, paddingX, paddingY)
obj.Width = newWidth
obj.Height = newHeight
}
}
for _, edge := range g.Edges {
endpointLabels := []string{}

View file

@ -46,7 +46,10 @@ type Shape interface {
// 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
GetDimensionsToFit(width, height, padding float64) (float64, float64)
// TODO note change to interface
GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64)
GetDefaultPadding() (paddingX, paddingY float64)
// Perimeter returns a slice of geo.Intersectables that together constitute the shape border
Perimeter() []geo.Intersectable
@ -93,8 +96,12 @@ func (s baseShape) GetInnerTopLeft(_, _, padding float64) geo.Point {
// return the minimum shape dimensions needed to fit content (width x height)
// in the shape's innerBox with padding
func (s baseShape) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
return width + padding*2, height + padding*2
func (s baseShape) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
return width + paddingX, height + paddingY
}
func (s baseShape) GetDefaultPadding() (paddingX, paddingY float64) {
return 100., 100.
}
func (s baseShape) Perimeter() []geo.Intersectable {

View file

@ -71,14 +71,14 @@ func (s shapeCallout) GetSVGPathData() []string {
}
}
func (s shapeCallout) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
func (s shapeCallout) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
// return the minimum shape dimensions needed to fit content (width x height)
// in the shape's innerBox with padding
baseHeight := height + padding*2
baseHeight := height + paddingY
if baseHeight < defaultTipHeight {
baseHeight *= 2
} else {
baseHeight += defaultTipHeight
}
return width + padding*2, baseHeight
return width + paddingX, baseHeight
}

View file

@ -33,8 +33,8 @@ func (s shapeCircle) AspectRatio1() bool {
return true
}
func (s shapeCircle) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
diameter := math.Ceil(math.Sqrt(2 * math.Pow(math.Max(width, height)+2*padding, 2)))
func (s shapeCircle) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
diameter := math.Ceil(math.Sqrt(2 * math.Pow(math.Max(width+paddingX, height+paddingY), 2)))
return diameter, diameter
}

View file

@ -19,3 +19,8 @@ func NewClass(box *geo.Box) Shape {
},
}
}
func (s shapeClass) GetDefaultPadding() (paddingX, paddingY float64) {
// TODO fix class row width measurements (see SQL table)
return 100, 0
}

View file

@ -58,9 +58,10 @@ func (s shapeCloud) GetInnerBox() *geo.Box {
return geo.NewBox(&insideTL, width, height)
}
func (s shapeCloud) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
width += padding
height += padding
func (s shapeCloud) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
// TODO /2?
width += paddingX
height += paddingY
aspectRatio := width / height
// use the inner box with the closest aspect ratio (wide, tall, or square box)
if aspectRatio > CLOUD_WIDE_ASPECT_BOUNDARY {
@ -116,3 +117,7 @@ func (s shapeCloud) GetSVGPathData() []string {
cloudPath(s.Box).PathData(),
}
}
func (s shapeCloud) GetDefaultPadding() (paddingX, paddingY float64) {
return 50, 50
}

View file

@ -18,3 +18,7 @@ func NewCode(box *geo.Box) Shape {
},
}
}
func (s shapeCode) GetDefaultPadding() (paddingX, paddingY float64) {
return 0, 0
}

View file

@ -77,8 +77,8 @@ func (s shapeCylinder) GetSVGPathData() []string {
}
}
func (s shapeCylinder) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
func (s shapeCylinder) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
// 2 arcs top, height + padding, 1 arc bottom
totalHeight := height + padding*2 + 3*defaultArcDepth
return width + padding*2, totalHeight
totalHeight := height + paddingY + 3*defaultArcDepth
return width + paddingX, totalHeight
}

View file

@ -55,8 +55,8 @@ func (s shapeDiamond) GetSVGPathData() []string {
}
}
func (s shapeDiamond) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
totalWidth := 2 * (width + 2*padding)
totalHeight := 2 * (height + 2*padding)
func (s shapeDiamond) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := 2 * (width + paddingX)
totalHeight := 2 * (height + paddingY)
return totalWidth, totalHeight
}

View file

@ -52,7 +52,7 @@ func (s shapeDocument) GetSVGPathData() []string {
}
}
func (s shapeDocument) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
baseHeight := (height + padding*2) * docPathHeight / docPathInnerBottom
return width + padding*2, baseHeight
func (s shapeDocument) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
baseHeight := (height + paddingX) * docPathHeight / docPathInnerBottom
return width + paddingY, baseHeight
}

View file

@ -49,7 +49,7 @@ func (s shapeHexagon) GetSVGPathData() []string {
}
}
func (s shapeHexagon) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
totalWidth := 2 * (width + 2*padding)
return totalWidth, height + 2*padding
func (s shapeHexagon) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := 2 * (width + paddingX)
return totalWidth, height + paddingY
}

View file

@ -20,3 +20,7 @@ func NewImage(box *geo.Box) Shape {
func (s shapeImage) IsRectangular() bool {
return true
}
func (s shapeImage) GetDefaultPadding() (paddingX, paddingY float64) {
return 0, 0
}

View file

@ -29,11 +29,11 @@ func (s shapeOval) GetInnerBox() *geo.Box {
return geo.NewBox(&insideTL, width, height)
}
func (s shapeOval) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
func (s shapeOval) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
theta := math.Atan2(height, width)
// add padding in direction of diagonal so there is padding distance between top left and border
paddedWidth := width + 2*padding*math.Cos(theta)
paddedHeight := height + 2*padding*math.Sin(theta)
paddedWidth := width + paddingX*math.Cos(theta)
paddedHeight := height + paddingY*math.Sin(theta)
// see https://stackoverflow.com/questions/433371/ellipse-bounding-a-rectangle
return math.Ceil(math.Sqrt2 * paddedWidth), math.Ceil(math.Sqrt2 * paddedHeight)
}

View file

@ -72,13 +72,13 @@ func (s shapePackage) GetSVGPathData() []string {
}
}
func (s shapePackage) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
innerHeight := height + padding*2
func (s shapePackage) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
innerHeight := height + paddingY
// We want to compute what the topHeight will be to add to inner height;
// topHeight=(verticalScalar * totalHeight) and totalHeight=(topHeight + innerHeight)
// so solving for topHeight we get: topHeight=innerHeight * (verticalScalar/(1-verticalScalar))
topHeight := innerHeight * packageVerticalScalar / (1. - packageVerticalScalar)
totalHeight := innerHeight + math.Min(topHeight, packageTopMaxHeight)
return width + padding*2, totalHeight
return width + paddingX, totalHeight
}

View file

@ -86,9 +86,9 @@ func (s shapePage) GetSVGPathData() []string {
}
}
func (s shapePage) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
totalWidth := width + padding*2
totalHeight := height + padding*2
func (s shapePage) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + paddingX
totalHeight := height + paddingY
// add space for corner with short pages
if totalHeight < 3*pageCornerHeight {
totalWidth += pageCornerWidth

View file

@ -54,7 +54,7 @@ func (s shapeParallelogram) GetSVGPathData() []string {
}
}
func (s shapeParallelogram) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
totalWidth := width + padding*2 + parallelWedgeWidth*2
return totalWidth, height + padding*2
func (s shapeParallelogram) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + paddingX + parallelWedgeWidth*2
return totalWidth, height + paddingY
}

View file

@ -66,11 +66,11 @@ func (s shapePerson) GetSVGPathData() []string {
}
}
func (s shapePerson) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
totalWidth := width + padding*2
func (s shapePerson) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + paddingX
// see shapePackage
shoulderWidth := totalWidth * personShoulderWidthFactor / (1 - 2*personShoulderWidthFactor)
totalWidth += 2 * shoulderWidth
totalHeight := height + padding*2
totalHeight := height + paddingY
return totalWidth, totalHeight
}

View file

@ -73,8 +73,8 @@ func (s shapeQueue) GetSVGPathData() []string {
}
}
func (s shapeQueue) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
func (s shapeQueue) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
// 1 arc left, width+ padding, 2 arcs right
totalWidth := 3*defaultArcDepth + width + padding*2
return totalWidth, height + padding*2
totalWidth := 3*defaultArcDepth + width + paddingX
return totalWidth, height + paddingY
}

View file

@ -27,7 +27,7 @@ func (s shapeRealSquare) IsRectangular() bool {
return true
}
func (s shapeRealSquare) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
sideLength := math.Max(width+padding*2, height+padding*2)
func (s shapeRealSquare) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
sideLength := math.Max(width+paddingX, height+paddingY)
return sideLength, sideLength
}

View file

@ -54,7 +54,7 @@ func (s shapeStep) GetSVGPathData() []string {
}
}
func (s shapeStep) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
totalWidth := width + padding*2 + 2*STEP_WEDGE_WIDTH
return totalWidth, height + padding*2
func (s shapeStep) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + paddingX + 2*STEP_WEDGE_WIDTH
return totalWidth, height + paddingY
}

View file

@ -56,7 +56,7 @@ func (s shapeStoredData) GetSVGPathData() []string {
}
}
func (s shapeStoredData) GetDimensionsToFit(width, height, padding float64) (float64, float64) {
totalWidth := width + padding*2 + 2*storedDataWedgeWidth
return totalWidth, height + padding*2
func (s shapeStoredData) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + paddingX + 2*storedDataWedgeWidth
return totalWidth, height + paddingY
}

View file

@ -19,3 +19,7 @@ func NewTable(box *geo.Box) Shape {
},
}
}
func (s shapeTable) GetDefaultPadding() (paddingX, paddingY float64) {
return 0, 0
}

View file

@ -19,3 +19,7 @@ func NewText(box *geo.Box) Shape {
},
}
}
func (s shapeText) GetDefaultPadding() (paddingX, paddingY float64) {
return 0, 0
}