This commit is contained in:
Gavin Nishizawa 2023-07-11 16:30:16 -07:00
parent d25d1a3bf0
commit b6795e65e1
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD
2 changed files with 90 additions and 75 deletions

View file

@ -341,7 +341,7 @@ func (edge *Edge) TraceToShape(points []*geo.Point, startIndex, endIndex int) (n
points[startIndex] = intersections[0]
startingSegment.End = intersections[0]
// if the segment becomes too short, just merge it with the next segment
if startIndex < len(points) && startingSegment.Length() < MIN_SEGMENT_LEN {
if startIndex+1 < len(points)-1 && startingSegment.Length() < MIN_SEGMENT_LEN {
points[startIndex+1] = points[startIndex]
startIndex++
}
@ -354,7 +354,7 @@ func (edge *Edge) TraceToShape(points []*geo.Point, startIndex, endIndex int) (n
points[startIndex] = intersections[0]
startingSegment.End = intersections[0]
// if the segment becomes too short, just merge it with the next segment
if startIndex < len(points) && startingSegment.Length() < MIN_SEGMENT_LEN {
if startIndex+1 < len(points)-1 && startingSegment.Length() < MIN_SEGMENT_LEN {
points[startIndex+1] = points[startIndex]
startIndex++
}

View file

@ -670,10 +670,10 @@ func getRanks(g *d2graph.Graph, isHorizontal bool) (ranks [][]*d2graph.Object, o
for _, obj := range g.Objects {
if !obj.IsContainer() {
if !isHorizontal {
y := obj.TopLeft.Y + obj.Height/2
y := math.Ceil(obj.TopLeft.Y + obj.Height/2)
alignedObjects[y] = append(alignedObjects[y], obj)
} else {
x := obj.TopLeft.X + obj.Width/2
x := math.Ceil(obj.TopLeft.X + obj.Width/2)
alignedObjects[x] = append(alignedObjects[x], obj)
}
}
@ -717,35 +717,6 @@ func getRanks(g *d2graph.Graph, isHorizontal bool) (ranks [][]*d2graph.Object, o
return ranks, objectRanks, startingParentRanks, endingParentRanks
}
func getRankRange(rank []*d2graph.Object, isHorizontal bool) (min, max float64) {
min = math.Inf(1)
max = math.Inf(-1)
for _, obj := range rank {
if isHorizontal {
min = math.Min(min, obj.TopLeft.X)
max = math.Max(max, obj.TopLeft.X+obj.Width)
} else {
min = math.Min(min, obj.TopLeft.Y)
max = math.Max(max, obj.TopLeft.Y+obj.Height)
}
}
return
}
func getPositions(ranks [][]*d2graph.Object, isHorizontal bool) (starts, centers, ends []float64) {
for _, objects := range ranks {
min, max := getRankRange(objects, isHorizontal)
starts = append(starts, min)
if isHorizontal {
centers = append(centers, objects[0].TopLeft.X+objects[0].Width/2.)
} else {
centers = append(centers, objects[0].TopLeft.Y+objects[0].Height/2.)
}
ends = append(ends, max)
}
return
}
// shift everything down by distance if it is at or below start position
func shiftDown(g *d2graph.Graph, start, distance float64, isHorizontal bool) {
if isHorizontal {
@ -992,47 +963,50 @@ func shiftReachableDown(g *d2graph.Graph, obj *d2graph.Object, start, distance f
}
increasedMargins := make(map[*d2graph.Object]struct{})
shiftedObjects := make([]*d2graph.Object, 0, len(shifted))
movedObjects := make([]*d2graph.Object, 0, len(shifted))
for obj := range shifted {
shiftedObjects = append(shiftedObjects, obj)
movedObjects = append(movedObjects, obj)
}
for _, shifted := range shiftedObjects {
for obj := range grown {
movedObjects = append(movedObjects, obj)
}
for _, moved := range movedObjects {
counts := true
// check if any other shifted is directly above
for _, other := range shiftedObjects {
if other == shifted || shifted.IsDescendantOf(other) {
for _, other := range movedObjects {
if other == moved {
continue
}
if isHorizontal {
if other.TopLeft.Y+other.Height < shifted.TopLeft.Y ||
shifted.TopLeft.Y+shifted.Height < other.TopLeft.Y {
if other.TopLeft.Y+other.Height < moved.TopLeft.Y ||
moved.TopLeft.Y+moved.Height < other.TopLeft.Y {
// doesn't line up vertically
continue
}
// above and within threshold
if other.TopLeft.X+other.Width < shifted.TopLeft.X &&
shifted.TopLeft.X < other.TopLeft.X+other.Width+threshold {
if other.TopLeft.X < moved.TopLeft.X &&
moved.TopLeft.X < other.TopLeft.X+other.Width+threshold {
counts = false
break
}
} else {
if other.TopLeft.X+other.Width < shifted.TopLeft.X ||
shifted.TopLeft.X+shifted.Width < other.TopLeft.X {
if other.TopLeft.X+other.Width < moved.TopLeft.X ||
moved.TopLeft.X+moved.Width < other.TopLeft.X {
// doesn't line up horizontally
continue
}
// above and within threshold
if other.TopLeft.Y+other.Height < shifted.TopLeft.Y &&
shifted.TopLeft.Y < other.TopLeft.Y+other.Height+threshold {
if other.TopLeft.Y < moved.TopLeft.Y &&
moved.TopLeft.Y < other.TopLeft.Y+other.Height+threshold {
counts = false
break
}
}
}
if counts {
increasedMargins[shifted] = struct{}{}
increasedMargins[moved] = struct{}{}
}
}
@ -1041,7 +1015,6 @@ func shiftReachableDown(g *d2graph.Graph, obj *d2graph.Object, start, distance f
func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
ranks, objectRanks, startingParentRanks, endingParentRanks := getRanks(g, isHorizontal)
starts, _, ends := getPositions(ranks, isHorizontal)
// shifting bottom rank down first, then moving up to next rank
for rank := len(ranks) - 1; rank >= 0; rank-- {
@ -1059,16 +1032,18 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
}
}
var startingAncestorDeltas []float64
startingAncestorPositions := make(map[*d2graph.Object]float64)
for len(startingParents) > 0 {
var delta float64
var ancestors []*d2graph.Object
for _, parent := range startingParents {
_, padding := getSpacing(parent)
if _, has := startingAncestorPositions[parent]; !has {
startingAncestorPositions[parent] = math.Inf(1)
}
if isHorizontal {
delta = math.Max(delta, padding.left)
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], parent.TopLeft.X+rankSep/2.-MIN_MARGIN-padding.left)
} else {
delta = math.Max(delta, padding.top)
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], parent.TopLeft.Y+rankSep/2.-MIN_MARGIN-padding.top)
}
for _, child := range parent.ChildrenArray {
if r, has := objectRanks[child]; has {
@ -1084,30 +1059,33 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
}
margin, _ := getSpacing(child)
if isHorizontal {
delta = math.Max(delta, margin.left)
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], child.TopLeft.X-margin.left-MIN_MARGIN)
} else {
delta = math.Max(delta, margin.top)
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], child.TopLeft.Y-margin.top-MIN_MARGIN)
}
}
if parent.Parent != g.Root {
ancestors = append(ancestors, parent.Parent)
}
}
startingAncestorDeltas = append(startingAncestorDeltas, delta)
startingParents = ancestors
}
var endingAncestorDeltas []float64
endingAncestorPositions := make(map[*d2graph.Object]float64)
for len(endingParents) > 0 {
var delta float64
delta := 0.
var ancestors []*d2graph.Object
for _, parent := range endingParents {
_, padding := getSpacing(parent)
if _, has := endingAncestorPositions[parent]; !has {
endingAncestorPositions[parent] = math.Inf(-1)
}
if isHorizontal {
delta = math.Max(delta, padding.right)
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], parent.TopLeft.X+parent.Width-rankSep/2+MIN_MARGIN+padding.right)
} else {
delta = math.Max(delta, padding.bottom)
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], parent.TopLeft.Y+parent.Height-rankSep/2+MIN_MARGIN+padding.bottom)
}
for _, child := range parent.ChildrenArray {
if r, has := objectRanks[child]; has {
@ -1124,24 +1102,42 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
margin, _ := getSpacing(child)
if isHorizontal {
delta = math.Max(delta, margin.right)
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], child.TopLeft.X+child.Width+margin.right+MIN_MARGIN)
} else {
delta = math.Max(delta, margin.bottom)
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], child.TopLeft.Y+child.Height+margin.bottom+MIN_MARGIN)
}
}
if parent.Parent != g.Root {
ancestors = append(ancestors, parent.Parent)
}
}
endingAncestorDeltas = append(endingAncestorDeltas, delta)
endingParents = ancestors
}
for i := len(endingAncestorDeltas) - 1; i >= 0; i-- {
endDelta := math.Max(0, MIN_MARGIN+endingAncestorDeltas[i]-rankSep/2.)
endingAncestorPositionOrder := make([]*d2graph.Object, 0, len(endingAncestorPositions))
for ancestor := range endingAncestorPositions {
endingAncestorPositionOrder = append(endingAncestorPositionOrder, ancestor)
}
// adjust rank ancestors bottom-up
sort.Slice(endingAncestorPositionOrder, func(i, j int) bool {
return endingAncestorPositions[endingAncestorPositionOrder[i]] > endingAncestorPositions[endingAncestorPositionOrder[j]]
})
for _, ancestor := range endingAncestorPositionOrder {
var endDelta float64
if isHorizontal {
endDelta = endingAncestorPositions[ancestor] - (ancestor.TopLeft.X + ancestor.Width)
} else {
endDelta = endingAncestorPositions[ancestor] - (ancestor.TopLeft.Y + ancestor.Height)
}
if endDelta > 0 {
// each nested container adds rankSep/2. space in rank direction
// +1 to not include edges at bottom
position := ends[rank] + float64(i)*rankSep/2. + 1
var position float64
if isHorizontal {
position = ancestor.TopLeft.X + ancestor.Width - 1
} else {
position = ancestor.TopLeft.Y + ancestor.Height - 1
}
for _, obj := range g.Objects {
if !obj.IsContainer() {
continue
@ -1159,11 +1155,30 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
shiftDown(g, position, endDelta, isHorizontal)
}
}
for i := 0; i < len(startingAncestorDeltas); i++ {
startDelta := math.Max(0, MIN_MARGIN+startingAncestorDeltas[i]-rankSep/2.)
if startDelta > 0 {
// each nested container adds rankSep/2. space in rank direction
position := starts[rank] - float64(i)*rankSep/2.
startingAncestorPositionOrder := make([]*d2graph.Object, 0, len(startingAncestorPositions))
for ancestor := range startingAncestorPositions {
startingAncestorPositionOrder = append(startingAncestorPositionOrder, ancestor)
}
// adjust rank ancestors bottom-up
sort.Slice(startingAncestorPositionOrder, func(i, j int) bool {
return startingAncestorPositions[startingAncestorPositionOrder[i]] > startingAncestorPositions[startingAncestorPositionOrder[j]]
})
for _, ancestor := range startingAncestorPositionOrder {
var endDelta float64
if isHorizontal {
endDelta = ancestor.TopLeft.X - startingAncestorPositions[ancestor]
} else {
endDelta = ancestor.TopLeft.Y - startingAncestorPositions[ancestor]
}
if endDelta > 0 {
var position float64
if isHorizontal {
position = ancestor.TopLeft.X + 1
} else {
position = ancestor.TopLeft.Y + 1
}
for _, obj := range g.Objects {
if !obj.IsContainer() {
continue
@ -1171,14 +1186,14 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
start := startingParentRanks[obj]
end := endingParentRanks[obj]
if start <= rank && rank <= end {
if isHorizontal && obj.TopLeft.X < position {
obj.Width += startDelta
} else if !isHorizontal && obj.TopLeft.Y < position {
obj.Height += startDelta
if isHorizontal && obj.TopLeft.X+obj.Width > position {
obj.Width += endDelta
} else if !isHorizontal && obj.TopLeft.Y+obj.Height > position {
obj.Height += endDelta
}
}
}
shiftDown(g, position, startDelta, isHorizontal)
shiftDown(g, position, endDelta, isHorizontal)
}
}
}