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 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, // TODO: Refactor with a light abstract layer on top of AST implementing scenarios,
// variables, imports, substitutions and then a final set of structures representing // 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 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 { type Edge struct {
Index int `json:"index"` 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.ShapeImage &&
obj.Attributes.Shape.Value != d2target.ShapeSQLTable && obj.Attributes.Shape.Value != d2target.ShapeSQLTable &&
obj.Attributes.Shape.Value != d2target.ShapeClass { obj.Attributes.Shape.Value != d2target.ShapeClass {
obj.Width = DEFAULT_SHAPE_PADDING obj.Width = DEFAULT_SHAPE_SIZE
obj.Height = DEFAULT_SHAPE_PADDING obj.Height = DEFAULT_SHAPE_SIZE
if desiredWidth != 0 { if desiredWidth != 0 {
obj.Width = float64(desiredWidth) 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.Width = float64(go2.Max(defaultDims.Width, desiredWidth))
obj.Height = float64(go2.Max(defaultDims.Height, desiredHeight)) 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 { paddingX, paddingY := s.GetDefaultPadding()
case d2target.ShapeSquare, d2target.ShapeCircle:
if s.AspectRatio1() {
if desiredWidth != 0 || desiredHeight != 0 { if desiredWidth != 0 || desiredHeight != 0 {
paddingX = 0. paddingX = 0.
paddingY = 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) sideLength := math.Max(obj.Width+paddingX, obj.Height+paddingY)
obj.Width = sideLength obj.Width = sideLength
obj.Height = sideLength obj.Height = sideLength
} else {
default:
if desiredWidth == 0 { if desiredWidth == 0 {
obj.Width += float64(paddingX) obj.Width += float64(paddingX)
} }
@ -1170,12 +1157,12 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
obj.Height += float64(paddingY) 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] if desiredWidth == 0 && desiredHeight == 0 {
s := shape.NewShape(shapeType, contentBox) newWidth, newHeight := s.GetDimensionsToFit(contentBox.Width, contentBox.Height, paddingX, paddingY)
newWidth, newHeight := s.GetDimensionsToFit(contentBox.Width, contentBox.Height, paddingX/2) obj.Width = newWidth
obj.Width = newWidth obj.Height = newHeight
obj.Height = newHeight }
} }
for _, edge := range g.Edges { for _, edge := range g.Edges {
endpointLabels := []string{} 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 // 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, 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 returns a slice of geo.Intersectables that together constitute the shape border
Perimeter() []geo.Intersectable 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) // return the minimum shape dimensions needed to fit content (width x height)
// in the shape's innerBox with padding // in the shape's innerBox with padding
func (s baseShape) GetDimensionsToFit(width, height, padding float64) (float64, float64) { func (s baseShape) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
return width + padding*2, height + padding*2 return width + paddingX, height + paddingY
}
func (s baseShape) GetDefaultPadding() (paddingX, paddingY float64) {
return 100., 100.
} }
func (s baseShape) Perimeter() []geo.Intersectable { 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) // return the minimum shape dimensions needed to fit content (width x height)
// in the shape's innerBox with padding // in the shape's innerBox with padding
baseHeight := height + padding*2 baseHeight := height + paddingY
if baseHeight < defaultTipHeight { if baseHeight < defaultTipHeight {
baseHeight *= 2 baseHeight *= 2
} else { } else {
baseHeight += defaultTipHeight baseHeight += defaultTipHeight
} }
return width + padding*2, baseHeight return width + paddingX, baseHeight
} }

View file

@ -33,8 +33,8 @@ func (s shapeCircle) AspectRatio1() bool {
return true return true
} }
func (s shapeCircle) GetDimensionsToFit(width, height, padding float64) (float64, float64) { func (s shapeCircle) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
diameter := math.Ceil(math.Sqrt(2 * math.Pow(math.Max(width, height)+2*padding, 2))) diameter := math.Ceil(math.Sqrt(2 * math.Pow(math.Max(width+paddingX, height+paddingY), 2)))
return diameter, diameter 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) return geo.NewBox(&insideTL, width, height)
} }
func (s shapeCloud) GetDimensionsToFit(width, height, padding float64) (float64, float64) { func (s shapeCloud) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
width += padding // TODO /2?
height += padding width += paddingX
height += paddingY
aspectRatio := width / height aspectRatio := width / height
// use the inner box with the closest aspect ratio (wide, tall, or square box) // use the inner box with the closest aspect ratio (wide, tall, or square box)
if aspectRatio > CLOUD_WIDE_ASPECT_BOUNDARY { if aspectRatio > CLOUD_WIDE_ASPECT_BOUNDARY {
@ -116,3 +117,7 @@ func (s shapeCloud) GetSVGPathData() []string {
cloudPath(s.Box).PathData(), 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 // 2 arcs top, height + padding, 1 arc bottom
totalHeight := height + padding*2 + 3*defaultArcDepth totalHeight := height + paddingY + 3*defaultArcDepth
return width + padding*2, totalHeight 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) { func (s shapeDiamond) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := 2 * (width + 2*padding) totalWidth := 2 * (width + paddingX)
totalHeight := 2 * (height + 2*padding) totalHeight := 2 * (height + paddingY)
return totalWidth, totalHeight return totalWidth, totalHeight
} }

View file

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

View file

@ -20,3 +20,7 @@ func NewImage(box *geo.Box) Shape {
func (s shapeImage) IsRectangular() bool { func (s shapeImage) IsRectangular() bool {
return true 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) 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) theta := math.Atan2(height, width)
// add padding in direction of diagonal so there is padding distance between top left and border // add padding in direction of diagonal so there is padding distance between top left and border
paddedWidth := width + 2*padding*math.Cos(theta) paddedWidth := width + paddingX*math.Cos(theta)
paddedHeight := height + 2*padding*math.Sin(theta) paddedHeight := height + paddingY*math.Sin(theta)
// see https://stackoverflow.com/questions/433371/ellipse-bounding-a-rectangle // see https://stackoverflow.com/questions/433371/ellipse-bounding-a-rectangle
return math.Ceil(math.Sqrt2 * paddedWidth), math.Ceil(math.Sqrt2 * paddedHeight) 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) { func (s shapePackage) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
innerHeight := height + padding*2 innerHeight := height + paddingY
// We want to compute what the topHeight will be to add to inner height; // We want to compute what the topHeight will be to add to inner height;
// topHeight=(verticalScalar * totalHeight) and totalHeight=(topHeight + innerHeight) // topHeight=(verticalScalar * totalHeight) and totalHeight=(topHeight + innerHeight)
// so solving for topHeight we get: topHeight=innerHeight * (verticalScalar/(1-verticalScalar)) // so solving for topHeight we get: topHeight=innerHeight * (verticalScalar/(1-verticalScalar))
topHeight := innerHeight * packageVerticalScalar / (1. - packageVerticalScalar) topHeight := innerHeight * packageVerticalScalar / (1. - packageVerticalScalar)
totalHeight := innerHeight + math.Min(topHeight, packageTopMaxHeight) 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) { func (s shapePage) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + padding*2 totalWidth := width + paddingX
totalHeight := height + padding*2 totalHeight := height + paddingY
// add space for corner with short pages // add space for corner with short pages
if totalHeight < 3*pageCornerHeight { if totalHeight < 3*pageCornerHeight {
totalWidth += pageCornerWidth totalWidth += pageCornerWidth

View file

@ -54,7 +54,7 @@ func (s shapeParallelogram) GetSVGPathData() []string {
} }
} }
func (s shapeParallelogram) GetDimensionsToFit(width, height, padding float64) (float64, float64) { func (s shapeParallelogram) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + padding*2 + parallelWedgeWidth*2 totalWidth := width + paddingX + parallelWedgeWidth*2
return totalWidth, height + padding*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) { func (s shapePerson) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + padding*2 totalWidth := width + paddingX
// see shapePackage // see shapePackage
shoulderWidth := totalWidth * personShoulderWidthFactor / (1 - 2*personShoulderWidthFactor) shoulderWidth := totalWidth * personShoulderWidthFactor / (1 - 2*personShoulderWidthFactor)
totalWidth += 2 * shoulderWidth totalWidth += 2 * shoulderWidth
totalHeight := height + padding*2 totalHeight := height + paddingY
return totalWidth, totalHeight 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 // 1 arc left, width+ padding, 2 arcs right
totalWidth := 3*defaultArcDepth + width + padding*2 totalWidth := 3*defaultArcDepth + width + paddingX
return totalWidth, height + padding*2 return totalWidth, height + paddingY
} }

View file

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

View file

@ -54,7 +54,7 @@ func (s shapeStep) GetSVGPathData() []string {
} }
} }
func (s shapeStep) GetDimensionsToFit(width, height, padding float64) (float64, float64) { func (s shapeStep) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + padding*2 + 2*STEP_WEDGE_WIDTH totalWidth := width + paddingX + 2*STEP_WEDGE_WIDTH
return totalWidth, height + padding*2 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) { func (s shapeStoredData) GetDimensionsToFit(width, height, paddingX, paddingY float64) (float64, float64) {
totalWidth := width + padding*2 + 2*storedDataWedgeWidth totalWidth := width + paddingX + 2*storedDataWedgeWidth
return totalWidth, height + padding*2 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
}