package quality

import (
	

	
	
)

func countNonSharedCrossings( []*layoutgraph.Edge,  *limits.WorkGuard) (int64, error) {
	var  int64
	for ,  := range  {
		if  := .Step();  != nil {
			return 0, 
		}
		for  :=  + 1;  < len(); ++ {
			// Charge every pair even when one route has no segments. Iterating a
			// large collection of incomplete routes is still quadratic work.
			if  := .Step();  != nil {
				return 0, 
			}
			,  := countEdgeCrossings(, [], )
			if  != nil {
				return 0, 
			}
			 += 
		}
	}
	return , nil
}

func countEdgeCrossings(,  *layoutgraph.Edge,  *limits.WorkGuard) (int64, error) {
	var  int64
	for  := 0;  < len(.Points)-1; ++ {
		if  := .Step();  != nil {
			return 0, 
		}
		for  := 0;  < len(.Points)-1; ++ {
			if  := .Step();  != nil {
				return 0, 
			}
			if isNonSharedCrossing(, , , ) {
				++
			}
		}
	}
	return , nil
}

func isNonSharedCrossing(,  *layoutgraph.Edge, ,  int) bool {
	if !nonParallelIntersection(
		.Points[],
		.Points[+1],
		.Points[],
		.Points[+1],
	) {
		return false
	}

	// Skip intersections at the exact end of the segment to avoid counting
	// bends off shared edges.
	 := .Points[].X
	 := .Points[].Y
	if  == .Points[+1].X &&
		( == .Points[].X ||  == .Points[+1].X) {
		return false
	}
	if  == .Points[+1].Y &&
		( == .Points[].Y ||  == .Points[+1].Y) {
		return false
	}
	return true
}

// orientation returns a positive value for a clockwise turn, a negative value
// for a counter-clockwise turn, and zero for collinear points.
func orientation(, ,  *geo.Point) float64 {
	 := .X - .X
	 := .Y - .Y
	 := .X - .X
	 := .Y - .Y
	return * - *
}

func equalSigns(,  float64) bool {
	return  > 0 &&  > 0 ||  == 0 &&  == 0 ||  < 0 &&  < 0
}

// nonParallelIntersection reports whether segments ab and cd intersect at an
// angle. Collinear overlap is intentionally not a crossing for layout scoring.
func nonParallelIntersection(, , ,  *geo.Point) bool {
	 := orientation(, , )
	 := orientation(, , )
	if equalSigns(, ) {
		return false
	}

	 := orientation(, , )
	 := orientation(, , )
	return !equalSigns(, )
}