// Package labeling places node, icon, edge, and arrowhead labels on a routed // layout graph. It owns placement policy and search; layoutgraph owns the // mutable graph records and geometry primitives.
package labeling import ( ) // searchRange is the fraction of an edge route searched for an unlocked // label. It is deliberately local to label placement rather than sharing the // routing package's tunnel range type. type searchRange struct { start float64 end float64 } // The order of preferred edge-label positions. var edgeLabelPreferenceOrder = []label.Position{ label.OutsideTopCenter, label.OutsideBottomCenter, label.OutsideTopLeft, label.OutsideTopRight, label.OutsideBottomLeft, label.OutsideBottomRight, label.InsideMiddleCenter, label.InsideMiddleLeft, label.InsideMiddleRight, } var nodeLabelPositionOrder = []label.Position{ label.InsideMiddleCenter, label.InsideTopCenter, label.InsideBottomCenter, label.InsideMiddleLeft, label.InsideMiddleRight, label.InsideTopLeft, label.InsideTopRight, label.InsideBottomLeft, label.InsideBottomRight, label.OutsideTopCenter, label.OutsideBottomCenter, label.OutsideLeftMiddle, label.OutsideRightMiddle, label.OutsideTopLeft, label.OutsideTopRight, label.OutsideBottomLeft, label.OutsideBottomRight, label.OutsideLeftTop, label.OutsideLeftBottom, label.OutsideRightTop, label.OutsideRightBottom, } var containerLabelPositionOrder = []label.Position{ label.InsideTopCenter, label.OutsideTopCenter, label.InsideBottomCenter, label.OutsideBottomCenter, label.OutsideTopLeft, label.OutsideTopRight, label.OutsideBottomLeft, label.OutsideBottomRight, label.OutsideLeftMiddle, label.OutsideRightMiddle, label.OutsideLeftTop, label.OutsideLeftBottom, label.OutsideRightTop, label.OutsideRightBottom, label.InsideTopLeft, label.InsideTopRight, label.InsideBottomLeft, label.InsideBottomRight, label.InsideMiddleLeft, label.InsideMiddleRight, label.InsideMiddleCenter, } // Initialize reserves each explicit/default node-label and icon position // before placement begins. func ( *layoutgraph.Graph) { for , := range .Nodes { setDefaultLabelPlacement() if .Icon != nil && .Icon.Position != label.Unset { .Icon.FixPosition() } } } func setDefaultLabelPlacement( *layoutgraph.Node) { if .Label == nil { return } if .Label.Position == label.Unset { .Label.Position = labelPositionPreferences()[0] } else { .Label.FixPosition() } } func compareLabelPositions( *layoutgraph.Node, , label.Position) int { := func( label.Position) int { := -1 for , := range []nodeshape.LabelTier{nodeshape.Good, nodeshape.OK, nodeshape.Unideal, nodeshape.Bad} { if , := .Shape.LabelPositionPreferences()[]; { = + 1 } } return } , := (), () if < { return 1 } if > { return -1 } return 0 } func labelPositionPreferences( *layoutgraph.Node) []label.Position { var []label.Position for , := range labelPositionPreferenceTranches() { = append(, ...) } return } func labelPositionPreferenceTranches( *layoutgraph.Node) [][]label.Position { := nodeLabelPositionOrder if .IsContainer() { = containerLabelPositionOrder } := make([][]label.Position, 0, 4) for , := range []nodeshape.LabelTier{nodeshape.Good, nodeshape.OK, nodeshape.Unideal, nodeshape.Bad} { := .Shape.LabelPositionPreferences() var []label.Position for , := range { if , := []; { = append(, ) } } = append(, ) } return }