extend previous segment to target if last segment is very short
This commit is contained in:
parent
25e37fd0c4
commit
54f34d72ad
4 changed files with 55 additions and 4 deletions
|
|
@ -30,6 +30,8 @@ var setupJS string
|
||||||
//go:embed dagre.js
|
//go:embed dagre.js
|
||||||
var dagreJS string
|
var dagreJS string
|
||||||
|
|
||||||
|
const MIN_SEGMENT_LEN = 10
|
||||||
|
|
||||||
type ConfigurableOpts struct {
|
type ConfigurableOpts struct {
|
||||||
NodeSep int `json:"nodesep"`
|
NodeSep int `json:"nodesep"`
|
||||||
EdgeSep int `json:"edgesep"`
|
EdgeSep int `json:"edgesep"`
|
||||||
|
|
@ -247,6 +249,47 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// arrowheads can appear broken if segments are very short from dagre routing a point just outside the shape
|
||||||
|
// 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 {
|
||||||
|
// 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]
|
||||||
|
nextEnd := points[startIndex+2]
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
extended := *geo.NewSegment(nextEnd, extendedStart)
|
||||||
|
|
||||||
|
if intersections := edge.Src.Box.Intersections(extended); len(intersections) > 0 {
|
||||||
|
start = intersections[0]
|
||||||
|
startIndex += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !end.Equals(points[len(points)-1]) && endIndex-2 >= 0 {
|
||||||
|
newEndingSegment := *geo.NewSegment(end, points[endIndex-1])
|
||||||
|
if newEndingSegment.Length() < 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()
|
||||||
|
extended := *geo.NewSegment(prevStart, extendedEnd)
|
||||||
|
|
||||||
|
if intersections := edge.Dst.Box.Intersections(extended); len(intersections) > 0 {
|
||||||
|
end = intersections[0]
|
||||||
|
endIndex -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Attributes.Shape.Value)], edge.Src.Box)
|
srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Attributes.Shape.Value)], edge.Src.Box)
|
||||||
dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Attributes.Shape.Value)], edge.Dst.Box)
|
dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Attributes.Shape.Value)], edge.Dst.Box)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,12 +187,12 @@ func (p *Point) DistanceToLine(p1, p2 *Point) float64 {
|
||||||
|
|
||||||
// Moves the given point by Vector
|
// Moves the given point by Vector
|
||||||
func (start *Point) AddVector(v Vector) *Point {
|
func (start *Point) AddVector(v Vector) *Point {
|
||||||
return start.toVector().Add(v).ToPoint()
|
return start.ToVector().Add(v).ToPoint()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a Vector of the size between start and endpoint, pointing to endpoint
|
// Creates a Vector of the size between start and endpoint, pointing to endpoint
|
||||||
func (start *Point) VectorTo(endpoint *Point) Vector {
|
func (start *Point) VectorTo(endpoint *Point) Vector {
|
||||||
return endpoint.toVector().Minus(start.toVector())
|
return endpoint.ToVector().Minus(start.ToVector())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Point) FormattedCoordinates() string {
|
func (p *Point) FormattedCoordinates() string {
|
||||||
|
|
@ -205,7 +205,7 @@ func (q *Point) OnSegment(p, r *Point) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a Vector pointing to point
|
// Creates a Vector pointing to point
|
||||||
func (endpoint *Point) toVector() Vector {
|
func (endpoint *Point) ToVector() Vector {
|
||||||
return []float64{endpoint.X, endpoint.Y}
|
return []float64{endpoint.X, endpoint.Y}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ func TestAddVector(t *testing.T) {
|
||||||
|
|
||||||
func TestToVector(t *testing.T) {
|
func TestToVector(t *testing.T) {
|
||||||
p := &Point{3.5, 6.7}
|
p := &Point{3.5, 6.7}
|
||||||
v := p.toVector()
|
v := p.ToVector()
|
||||||
|
|
||||||
if v[0] != p.X || v[1] != p.Y {
|
if v[0] != p.X || v[1] != p.Y {
|
||||||
t.Fatalf("Expected Vector (%v) coordinates to match the point (%v)", p, v)
|
t.Fatalf("Expected Vector (%v) coordinates to match the point (%v)", p, v)
|
||||||
|
|
|
||||||
|
|
@ -114,3 +114,11 @@ func (segment *Segment) GetBounds(segments []*Segment, buffer float64) (float64,
|
||||||
}
|
}
|
||||||
return floor, ceil
|
return floor, ceil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (segment Segment) Length() float64 {
|
||||||
|
return EuclideanDistance(segment.Start.X, segment.Start.Y, segment.End.X, segment.End.Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (segment Segment) ToVector() Vector {
|
||||||
|
return NewVector(segment.End.X-segment.Start.X, segment.End.Y-segment.Start.Y)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue