package placementcost

import (
	

	
)

// Experimental placement preferences. The completed-layout score is unchanged.
const flowSpineWeight = 1.0
const flowBranchWeight = 1.0

// flowContinuityCost treats paths through a node as a visual unit. An incoming
// and outgoing connection should have at least one recognizable continuation;
// branches should leave enough angular room to read their separate attachments.
// A fixed, small incident-degree limit bounds the pair work in every existing
// placement candidate. Group vessels, port-specific edges, and cross-container
// abstractions retain their existing placement treatment.
func flowContinuityCost( *layoutgraph.Node,  *edgeScratch) float64 {
	if .TopLeft == nil || len(.Edges) < 2 || len(.Edges) > 8 ||
		.Cluster != nil || .Sequence != nil || .HerdAssignment != nil ||
		len(.Graph.Containers[]) != 0 {
		return 0
	}
	const (
		 uint8 = 1 << iota
		
	)
	type  struct {
		       *layoutgraph.Node
		,        float64
		 uint8
	}
	var  [8]
	 := 0
	,  := .TopLeft.X+.Width/2, .TopLeft.Y+.Height/2
	for ,  := range .Edges {
		if .IsInvisible || .From == .To || .HasTableColumn() ||
			.HasSourceArrow() == .HasTargetArrow() || .nRepl[] !=  {
			continue
		}
		 := .aRepl[]
		if  == nil || .TopLeft == nil || .Container != .Container {
			continue
		}
		 := .To == 
		if .HasSourceArrow() {
			 = !
		}
		 := 
		if  {
			 = 
		}
		 := false
		for  := 0;  < ; ++ {
			if []. ==  {
				// Parallel edges share one geometric ray. Reciprocal edges
				// retain both roles regardless of their declaration order.
				[]. |= 
				 = true
				break
			}
		}
		if  {
			continue
		}
		,  := .TopLeft.X+.Width/2-, .TopLeft.Y+.Height/2-
		 := math.Hypot(, )
		if  == 0 {
			continue
		}
		[] = {,  / ,  / , }
		++
	}
	 := math.Inf(1)
	,  := 0.0, 0
	for  := 0;  < ; ++ {
		for  :=  + 1;  < ; ++ {
			 := math.Max(-1, math.Min(1, [].*[].+[].*[].))
			,  := []., [].
			if & != 0 && & != 0 ||
				& != 0 && & != 0 {
				 = math.Min(, 1+)
			}
			if & != 0 {
				// Directions less than 60 degrees apart compete for a small
				// visual wedge at the attachment; wider angles incur no cost.
				// A reciprocal pair can also be a continuation, but each pair
				// contributes to the branch average only once.
				 += math.Max(0, 2*-1)
				++
			}
		}
	}
	 := 0.0
	if !math.IsInf(, 1) {
		 += flowSpineWeight * 
	}
	if  > 0 {
		 += flowBranchWeight *  / float64()
	}
	return .Graph.TurnCost() * 
}