Merge pull request #1381 from gavin-ts/outside-bottom-labels

layout: end connections at outside labels
This commit is contained in:
gavin-ts 2023-06-08 17:25:06 -07:00 committed by GitHub
commit 8dc1d9a223
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 2333 additions and 1191 deletions

View file

@ -17,6 +17,7 @@
- In watch mode, images are cached by default across compiles. Can be disabled with flag `--img-cache=0`. [#1373](https://github.com/terrastruct/d2/pull/1373)
- Common invalid array separator `,` usage in class arrays returns a helpful error message [#1376](https://github.com/terrastruct/d2/pull/1376)
- Invalid `constraint` usage is met with an error message, preventing a common mistake of omitting `shape: sql_table` [#1379](https://github.com/terrastruct/d2/pull/1379)
- Connections now stop at all outside labels. [#1381](https://github.com/terrastruct/d2/pull/1381)
#### Bugfixes ⛑️

View file

@ -9,6 +9,8 @@ import (
"oss.terrastruct.com/d2/lib/shape"
)
const MIN_SEGMENT_LEN = 10
func (obj *Object) MoveWithDescendants(dx, dy float64) {
obj.TopLeft.X += dx
obj.TopLeft.Y += dy
@ -313,3 +315,72 @@ func (obj *Object) GetLabelTopLeft() *geo.Point {
)
return labelTL
}
func (edge *Edge) TraceToShape(points []*geo.Point, startIndex, endIndex int) (newStart, newEnd int) {
srcShape := edge.Src.ToShape()
dstShape := edge.Dst.ToShape()
// if an edge runs into an outside label, stop the edge at the label instead
overlapsOutsideLabel := false
if edge.Src.HasLabel() {
// assumes LabelPosition, LabelWidth, LabelHeight are all set if there is a label
labelPosition := label.Position(*edge.Src.LabelPosition)
if labelPosition.IsOutside() {
labelWidth := float64(edge.Src.LabelDimensions.Width)
labelHeight := float64(edge.Src.LabelDimensions.Height)
labelTL := labelPosition.GetPointOnBox(edge.Src.Box, label.PADDING, labelWidth, labelHeight)
startingSegment := geo.Segment{Start: points[startIndex+1], End: points[startIndex]}
labelBox := geo.NewBox(labelTL, labelWidth, labelHeight)
// add left/right padding to box
labelBox.TopLeft.X -= label.PADDING
labelBox.Width += 2 * label.PADDING
if intersections := labelBox.Intersections(startingSegment); len(intersections) > 0 {
overlapsOutsideLabel = true
// move starting segment to label intersection point
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 {
points[startIndex+1] = points[startIndex]
startIndex++
}
}
}
}
if !overlapsOutsideLabel {
// trace the edge to the specific shape's border
points[startIndex] = shape.TraceToShapeBorder(srcShape, points[startIndex], points[startIndex+1])
}
overlapsOutsideLabel = false
if edge.Dst.HasLabel() {
// assumes LabelPosition, LabelWidth, LabelHeight are all set if there is a label
labelPosition := label.Position(*edge.Dst.LabelPosition)
if labelPosition.IsOutside() {
labelWidth := float64(edge.Dst.LabelDimensions.Width)
labelHeight := float64(edge.Dst.LabelDimensions.Height)
labelTL := labelPosition.GetPointOnBox(edge.Dst.Box, label.PADDING, labelWidth, labelHeight)
endingSegment := geo.Segment{Start: points[endIndex-1], End: points[endIndex]}
labelBox := geo.NewBox(labelTL, labelWidth, labelHeight)
// add left/right padding to box
labelBox.TopLeft.X -= label.PADDING
labelBox.Width += 2 * label.PADDING
if intersections := labelBox.Intersections(endingSegment); len(intersections) > 0 {
overlapsOutsideLabel = true
// move ending segment to label intersection point
points[endIndex] = intersections[0]
endingSegment.End = intersections[0]
// if the segment becomes too short, just merge it with the previous segment
if endIndex-1 > 0 && endingSegment.Length() < MIN_SEGMENT_LEN {
points[endIndex-1] = points[endIndex]
endIndex--
}
}
}
}
if !overlapsOutsideLabel {
points[endIndex] = shape.TraceToShapeBorder(dstShape, points[endIndex], points[endIndex-1])
}
return startIndex, endIndex
}

View file

@ -21,7 +21,6 @@ import (
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/label"
"oss.terrastruct.com/d2/lib/log"
"oss.terrastruct.com/d2/lib/shape"
)
//go:embed setup.js
@ -31,9 +30,8 @@ var setupJS string
var dagreJS string
const (
MIN_SEGMENT_LEN = 10
MIN_RANK_SEP = 60
EDGE_LABEL_GAP = 20
MIN_RANK_SEP = 60
EDGE_LABEL_GAP = 20
)
type ConfigurableOpts struct {
@ -433,7 +431,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
// to fix this, we try extending the previous segment into the shape instead of having a very short segment
if !start.Equals(points[0]) && startIndex+2 < len(points) {
newStartingSegment := *geo.NewSegment(start, points[startIndex+1])
if newStartingSegment.Length() < MIN_SEGMENT_LEN {
if newStartingSegment.Length() < d2graph.MIN_SEGMENT_LEN {
// we don't want a very short segment right next to the source because it will mess up the arrowhead
// instead we want to extend the next segment into the shape border if possible
nextStart := points[startIndex+1]
@ -442,30 +440,32 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
// Note: in other direction to extend towards source
nextSegment := *geo.NewSegment(nextStart, nextEnd)
v := nextSegment.ToVector()
extendedStart := nextEnd.ToVector().Add(v.AddLength(MIN_SEGMENT_LEN)).ToPoint()
extendedStart := nextEnd.ToVector().Add(v.AddLength(d2graph.MIN_SEGMENT_LEN)).ToPoint()
extended := *geo.NewSegment(nextEnd, extendedStart)
if intersections := edge.Src.Box.Intersections(extended); len(intersections) > 0 {
start = intersections[0]
startIndex += 1
startIndex++
points[startIndex] = intersections[0]
start = points[startIndex]
}
}
}
if !end.Equals(points[len(points)-1]) && endIndex-2 >= 0 {
newEndingSegment := *geo.NewSegment(end, points[endIndex-1])
if newEndingSegment.Length() < MIN_SEGMENT_LEN {
if newEndingSegment.Length() < d2graph.MIN_SEGMENT_LEN {
// extend the prev segment into the shape border if possible
prevStart := points[endIndex-2]
prevEnd := points[endIndex-1]
prevSegment := *geo.NewSegment(prevStart, prevEnd)
v := prevSegment.ToVector()
extendedEnd := prevStart.ToVector().Add(v.AddLength(MIN_SEGMENT_LEN)).ToPoint()
extendedEnd := prevStart.ToVector().Add(v.AddLength(d2graph.MIN_SEGMENT_LEN)).ToPoint()
extended := *geo.NewSegment(prevStart, extendedEnd)
if intersections := edge.Dst.Box.Intersections(extended); len(intersections) > 0 {
end = intersections[0]
endIndex -= 1
endIndex--
points[endIndex] = intersections[0]
end = points[endIndex]
}
}
}
@ -489,41 +489,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
}
}
srcShape := edge.Src.ToShape()
dstShape := edge.Dst.ToShape()
// trace the edge to the specific shape's border
points[startIndex] = shape.TraceToShapeBorder(srcShape, start, points[startIndex+1])
// if an edge to a container runs into its label, stop the edge at the label instead
overlapsContainerLabel := false
if edge.Dst.IsContainer() && edge.Dst.Label.Value != "" && !dstShape.Is(shape.TEXT_TYPE) {
// assumes LabelPosition, LabelWidth, LabelHeight are all set if there is a label
labelWidth := float64(edge.Dst.LabelDimensions.Width)
labelHeight := float64(edge.Dst.LabelDimensions.Height)
labelTL := label.Position(*edge.Dst.LabelPosition).
GetPointOnBox(edge.Dst.Box, label.PADDING, labelWidth, labelHeight)
endingSegment := geo.Segment{Start: points[endIndex-1], End: points[endIndex]}
labelBox := geo.NewBox(labelTL, labelWidth, labelHeight)
// add left/right padding to box
labelBox.TopLeft.X -= label.PADDING
labelBox.Width += 2 * label.PADDING
if intersections := labelBox.Intersections(endingSegment); len(intersections) > 0 {
overlapsContainerLabel = true
// move ending segment to label intersection point
points[endIndex] = intersections[0]
endingSegment.End = intersections[0]
// if the segment becomes too short, just merge it with the previous segment
if endIndex-1 > 0 && endingSegment.Length() < MIN_SEGMENT_LEN {
points[endIndex-1] = points[endIndex]
endIndex--
}
}
}
if !overlapsContainerLabel {
points[endIndex] = shape.TraceToShapeBorder(dstShape, end, points[endIndex-1])
}
startIndex, endIndex = edge.TraceToShape(points, startIndex, endIndex)
points = points[startIndex : endIndex+1]
// build a curved path from the dagre route

View file

@ -501,12 +501,8 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
}
}
srcShape := edge.Src.ToShape()
dstShape := edge.Dst.ToShape()
// trace the edge to the specific shape's border
points[startIndex] = shape.TraceToShapeBorder(srcShape, points[startIndex], points[startIndex+1])
points[endIndex] = shape.TraceToShapeBorder(dstShape, points[endIndex], points[endIndex-1])
startIndex, endIndex = edge.TraceToShape(points, startIndex, endIndex)
points = points[startIndex : endIndex+1]
if edge.Label.Value != "" {
edge.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))

View file

@ -2761,6 +2761,7 @@ scenarios: {
loadFromFile(t, "multiple_offset"),
loadFromFile(t, "multiple_offset_left"),
loadFromFile(t, "multiple_box_selection"),
loadFromFile(t, "outside_bottom_labels"),
}
runa(t, tcs)

View file

@ -0,0 +1,15 @@
p1: Daphne Snickerdoodle {
shape: person
}
p2: Prudence McSnortle {
shape: person
}
p3: Polly Pizzazzle {
shape: person
}
p1 -> p3
p2 -> p3
p1 -> p3
p2 -> p3
p3 -> p2
p3 -> p1

View file

@ -0,0 +1,454 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "p1",
"type": "person",
"pos": {
"x": 0,
"y": 0
},
"width": 174,
"height": 116,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B3",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "Daphne Snickerdoodle",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 159,
"labelHeight": 21,
"labelPosition": "OUTSIDE_BOTTOM_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "p2",
"type": "person",
"pos": {
"x": 9,
"y": 447
},
"width": 157,
"height": 105,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B3",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "Prudence McSnortle",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 142,
"labelHeight": 21,
"labelPosition": "OUTSIDE_BOTTOM_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "p3",
"type": "person",
"pos": {
"x": 28,
"y": 242
},
"width": 118,
"height": 79,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B3",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "Polly Pizzazzle",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 103,
"labelHeight": 21,
"labelPosition": "OUTSIDE_BOTTOM_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(p1 -> p3)[0]",
"src": "p1",
"srcArrow": "none",
"dst": "p3",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 75,
"y": 142
},
{
"x": 68.5999984741211,
"y": 182
},
{
"x": 69,
"y": 202.1999969482422
},
{
"x": 77,
"y": 243
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p2 -> p3)[0]",
"src": "p2",
"srcArrow": "none",
"dst": "p3",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 87,
"y": 447
},
{
"x": 87,
"y": 407
},
{
"x": 87,
"y": 387
},
{
"x": 87,
"y": 347
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p1 -> p3)[1]",
"src": "p1",
"srcArrow": "none",
"dst": "p3",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 87,
"y": 142
},
{
"x": 87,
"y": 182
},
{
"x": 87,
"y": 202
},
{
"x": 87,
"y": 242
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p2 -> p3)[1]",
"src": "p2",
"srcArrow": "none",
"dst": "p3",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 98,
"y": 448
},
{
"x": 105.19999694824219,
"y": 407.20001220703125
},
{
"x": 105,
"y": 387
},
{
"x": 97,
"y": 347
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p3 -> p2)[0]",
"src": "p3",
"srcArrow": "none",
"dst": "p2",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 77,
"y": 347
},
{
"x": 69,
"y": 387
},
{
"x": 68.80000305175781,
"y": 407.20001220703125
},
{
"x": 76,
"y": 448
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p3 -> p1)[0]",
"src": "p3",
"srcArrow": "none",
"dst": "p1",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 97,
"y": 243
},
{
"x": 105,
"y": 202.1999969482422
},
{
"x": 105.4000015258789,
"y": 182
},
{
"x": 99,
"y": 142
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.4.2-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 176 579"><svg id="d2-svg" class="d2-3340817268" width="176" height="579" viewBox="-1 -1 176 579"><rect x="-1.000000" y="-1.000000" width="176.000000" height="579.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-3340817268 .text-bold {
font-family: "d2-3340817268-font-bold";
}
@font-face {
font-family: d2-3340817268-font-bold;
src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-3340817268 .fill-N1{fill:#0A0F25;}
.d2-3340817268 .fill-N2{fill:#676C7E;}
.d2-3340817268 .fill-N3{fill:#9499AB;}
.d2-3340817268 .fill-N4{fill:#CFD2DD;}
.d2-3340817268 .fill-N5{fill:#DEE1EB;}
.d2-3340817268 .fill-N6{fill:#EEF1F8;}
.d2-3340817268 .fill-N7{fill:#FFFFFF;}
.d2-3340817268 .fill-B1{fill:#0D32B2;}
.d2-3340817268 .fill-B2{fill:#0D32B2;}
.d2-3340817268 .fill-B3{fill:#E3E9FD;}
.d2-3340817268 .fill-B4{fill:#E3E9FD;}
.d2-3340817268 .fill-B5{fill:#EDF0FD;}
.d2-3340817268 .fill-B6{fill:#F7F8FE;}
.d2-3340817268 .fill-AA2{fill:#4A6FF3;}
.d2-3340817268 .fill-AA4{fill:#EDF0FD;}
.d2-3340817268 .fill-AA5{fill:#F7F8FE;}
.d2-3340817268 .fill-AB4{fill:#EDF0FD;}
.d2-3340817268 .fill-AB5{fill:#F7F8FE;}
.d2-3340817268 .stroke-N1{stroke:#0A0F25;}
.d2-3340817268 .stroke-N2{stroke:#676C7E;}
.d2-3340817268 .stroke-N3{stroke:#9499AB;}
.d2-3340817268 .stroke-N4{stroke:#CFD2DD;}
.d2-3340817268 .stroke-N5{stroke:#DEE1EB;}
.d2-3340817268 .stroke-N6{stroke:#EEF1F8;}
.d2-3340817268 .stroke-N7{stroke:#FFFFFF;}
.d2-3340817268 .stroke-B1{stroke:#0D32B2;}
.d2-3340817268 .stroke-B2{stroke:#0D32B2;}
.d2-3340817268 .stroke-B3{stroke:#E3E9FD;}
.d2-3340817268 .stroke-B4{stroke:#E3E9FD;}
.d2-3340817268 .stroke-B5{stroke:#EDF0FD;}
.d2-3340817268 .stroke-B6{stroke:#F7F8FE;}
.d2-3340817268 .stroke-AA2{stroke:#4A6FF3;}
.d2-3340817268 .stroke-AA4{stroke:#EDF0FD;}
.d2-3340817268 .stroke-AA5{stroke:#F7F8FE;}
.d2-3340817268 .stroke-AB4{stroke:#EDF0FD;}
.d2-3340817268 .stroke-AB5{stroke:#F7F8FE;}
.d2-3340817268 .background-color-N1{background-color:#0A0F25;}
.d2-3340817268 .background-color-N2{background-color:#676C7E;}
.d2-3340817268 .background-color-N3{background-color:#9499AB;}
.d2-3340817268 .background-color-N4{background-color:#CFD2DD;}
.d2-3340817268 .background-color-N5{background-color:#DEE1EB;}
.d2-3340817268 .background-color-N6{background-color:#EEF1F8;}
.d2-3340817268 .background-color-N7{background-color:#FFFFFF;}
.d2-3340817268 .background-color-B1{background-color:#0D32B2;}
.d2-3340817268 .background-color-B2{background-color:#0D32B2;}
.d2-3340817268 .background-color-B3{background-color:#E3E9FD;}
.d2-3340817268 .background-color-B4{background-color:#E3E9FD;}
.d2-3340817268 .background-color-B5{background-color:#EDF0FD;}
.d2-3340817268 .background-color-B6{background-color:#F7F8FE;}
.d2-3340817268 .background-color-AA2{background-color:#4A6FF3;}
.d2-3340817268 .background-color-AA4{background-color:#EDF0FD;}
.d2-3340817268 .background-color-AA5{background-color:#F7F8FE;}
.d2-3340817268 .background-color-AB4{background-color:#EDF0FD;}
.d2-3340817268 .background-color-AB5{background-color:#F7F8FE;}
.d2-3340817268 .color-N1{color:#0A0F25;}
.d2-3340817268 .color-N2{color:#676C7E;}
.d2-3340817268 .color-N3{color:#9499AB;}
.d2-3340817268 .color-N4{color:#CFD2DD;}
.d2-3340817268 .color-N5{color:#DEE1EB;}
.d2-3340817268 .color-N6{color:#EEF1F8;}
.d2-3340817268 .color-N7{color:#FFFFFF;}
.d2-3340817268 .color-B1{color:#0D32B2;}
.d2-3340817268 .color-B2{color:#0D32B2;}
.d2-3340817268 .color-B3{color:#E3E9FD;}
.d2-3340817268 .color-B4{color:#E3E9FD;}
.d2-3340817268 .color-B5{color:#EDF0FD;}
.d2-3340817268 .color-B6{color:#F7F8FE;}
.d2-3340817268 .color-AA2{color:#4A6FF3;}
.d2-3340817268 .color-AA4{color:#EDF0FD;}
.d2-3340817268 .color-AA5{color:#F7F8FE;}
.d2-3340817268 .color-AB4{color:#EDF0FD;}
.d2-3340817268 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g id="p1"><g class="shape" ><path d="M 174 116 H 0 V 114 C 0 94 19 76 49 68 C 33 61 23 50 23 38 C 23 17 51 0 87 0 C 122 0 151 17 151 38 C 151 50 141 61 125 69 C 155 78 174 95 174 115 V 116 H 174 Z" class=" stroke-B1 fill-B3" style="stroke-width:2;" /></g><text x="87.000000" y="137.000000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Daphne Snickerdoodle</text></g><g id="p2"><g class="shape" ><path d="M 166 552 H 9 V 551 C 9 533 26 517 53 509 C 38 502 29 492 29 481 C 29 462 55 447 87 447 C 119 447 145 462 145 481 C 145 492 136 502 121 509 C 148 517 165 533 165 551 V 552 H 166 Z" class=" stroke-B1 fill-B3" style="stroke-width:2;" /></g><text x="87.500000" y="573.000000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Prudence McSnortle</text></g><g id="p3"><g class="shape" ><path d="M 146 321 H 28 V 320 C 28 307 41 294 61 289 C 50 284 43 276 43 268 C 43 254 63 242 87 242 C 111 242 131 254 131 268 C 131 276 124 284 113 289 C 133 295 146 307 146 320 V 321 H 146 Z" class=" stroke-B1 fill-B3" style="stroke-width:2;" /></g><text x="87.000000" y="342.000000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Polly Pizzazzle</text></g><g id="(p1 -&gt; p3)[0]"><marker id="mk-3488378134" markerWidth="10.000000" markerHeight="12.000000" refX="7.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" class="connection fill-B1" stroke-width="2" /> </marker><path d="M 74.684019 143.974881 C 68.599998 182.000000 69.000000 202.199997 76.230342 239.074745" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3340817268)" /></g><g id="(p2 -&gt; p3)[0]"><path d="M 87.000000 445.000000 C 87.000000 407.000000 87.000000 387.000000 87.000000 351.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3340817268)" /></g><g id="(p1 -&gt; p3)[1]"><path d="M 87.000000 144.000000 C 87.000000 182.000000 87.000000 202.000000 87.000000 238.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3340817268)" /></g><g id="(p2 -&gt; p3)[1]"><path d="M 98.347571 446.030433 C 105.199997 407.200012 105.000000 387.000000 97.784465 350.922323" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3340817268)" /></g><g id="(p3 -&gt; p2)[0]"><path d="M 76.607768 348.961161 C 69.000000 387.000000 68.800003 407.200012 75.304859 444.060866" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3340817268)" /></g><g id="(p3 -&gt; p1)[0]"><path d="M 97.384829 241.037372 C 105.000000 202.199997 105.400002 182.000000 99.631962 145.949763" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3340817268)" /></g><mask id="d2-3340817268" maskUnits="userSpaceOnUse" x="-1" y="-1" width="176" height="579">
<rect x="-1" y="-1" width="176" height="579" fill="white"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,448 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "p1",
"type": "person",
"pos": {
"x": 12,
"y": 12
},
"width": 174,
"height": 116,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B3",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "Daphne Snickerdoodle",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 159,
"labelHeight": 21,
"labelPosition": "OUTSIDE_BOTTOM_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "p2",
"type": "person",
"pos": {
"x": 206,
"y": 23
},
"width": 157,
"height": 105,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B3",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "Prudence McSnortle",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 142,
"labelHeight": 21,
"labelPosition": "OUTSIDE_BOTTOM_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "p3",
"type": "person",
"pos": {
"x": 113,
"y": 334
},
"width": 160,
"height": 79,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B3",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "Polly Pizzazzle",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 103,
"labelHeight": 21,
"labelPosition": "OUTSIDE_BOTTOM_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(p1 -> p3)[0]",
"src": "p1",
"srcArrow": "none",
"dst": "p3",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 55.5,
"y": 154
},
{
"x": 55.5,
"y": 294
},
{
"x": 136.73199462890625,
"y": 294
},
{
"x": 137,
"y": 354
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p2 -> p3)[0]",
"src": "p2",
"srcArrow": "none",
"dst": "p3",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 245.25,
"y": 154
},
{
"x": 245.25,
"y": 194
},
{
"x": 205.30299377441406,
"y": 194
},
{
"x": 205,
"y": 334
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p1 -> p3)[1]",
"src": "p1",
"srcArrow": "none",
"dst": "p3",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 99,
"y": 154
},
{
"x": 99,
"y": 244
},
{
"x": 159.58900451660156,
"y": 244
},
{
"x": 160,
"y": 339
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p2 -> p3)[1]",
"src": "p2",
"srcArrow": "none",
"dst": "p3",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 284.5,
"y": 154
},
{
"x": 284.5,
"y": 244
},
{
"x": 228.16000366210938,
"y": 244
},
{
"x": 228,
"y": 339
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p3 -> p2)[0]",
"src": "p3",
"srcArrow": "none",
"dst": "p2",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 251,
"y": 353
},
{
"x": 251.01699829101562,
"y": 294
},
{
"x": 323.75,
"y": 294
},
{
"x": 323.75,
"y": 154
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(p3 -> p1)[0]",
"src": "p3",
"srcArrow": "none",
"dst": "p1",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 182,
"y": 335
},
{
"x": 182.4459991455078,
"y": 194
},
{
"x": 142.5,
"y": 194
},
{
"x": 142.5,
"y": 154
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1049,12 +1049,12 @@
"labelPercentage": 0,
"route": [
{
"x": 155,
"y": 169
"x": 163.5,
"y": 194.5
},
{
"x": 198.60000610351562,
"y": 303
"x": 200.3000030517578,
"y": 308.1000061035156
},
{
"x": 209.5,
@ -1096,12 +1096,12 @@
"labelPercentage": 0,
"route": [
{
"x": 134,
"y": 169
"x": 124.75,
"y": 194.5
},
{
"x": 86.5999984741211,
"y": 303
"x": 84.75,
"y": 308.1000061035156
},
{
"x": 74.75,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View file

@ -775,12 +775,12 @@
"labelPercentage": 0,
"route": [
{
"x": 127,
"y": 87
"x": 111.75,
"y": 112.5
},
{
"x": 85.1989974975586,
"y": 156.1999969482422
"x": 82.1500015258789,
"y": 161.3000030517578
},
{
"x": 74.75,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 458 KiB

After

Width:  |  Height:  |  Size: 458 KiB

View file

@ -681,8 +681,8 @@
"labelPercentage": 0,
"route": [
{
"x": 291,
"y": 99
"x": 290.6659851074219,
"y": 125
},
{
"x": 290.6659851074219,
@ -727,7 +727,7 @@
"route": [
{
"x": 334,
"y": 99
"y": 125
},
{
"x": 334,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 457 KiB

After

Width:  |  Height:  |  Size: 457 KiB

View file

@ -1048,12 +1048,12 @@
"labelPercentage": 0,
"route": [
{
"x": 162,
"y": 169
"x": 171,
"y": 194.5
},
{
"x": 210.8000030517578,
"y": 303
"x": 212.60000610351562,
"y": 308.1000061035156
},
{
"x": 223,
@ -1094,12 +1094,12 @@
"labelPercentage": 0,
"route": [
{
"x": 139,
"y": 169
"x": 129.25,
"y": 194.5
},
{
"x": 88.80000305175781,
"y": 303
"x": 86.8499984741211,
"y": 308.1000061035156
},
{
"x": 76.25,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View file

@ -1000,8 +1000,8 @@
"labelPercentage": 0,
"route": [
{
"x": 262,
"y": 262
"x": 261.6659851074219,
"y": 288
},
{
"x": 261.6659851074219,
@ -1046,7 +1046,7 @@
"route": [
{
"x": 305,
"y": 262
"y": 288
},
{
"x": 305,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View file

@ -632,8 +632,8 @@
"labelPercentage": 0,
"route": [
{
"x": 262,
"y": 99
"x": 261.6659851074219,
"y": 125
},
{
"x": 261.6659851074219,
@ -678,7 +678,7 @@
"route": [
{
"x": 305,
"y": 99
"y": 125
},
{
"x": 305,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB