protected void HandleParallelSegment(BspSegment splitter, BspSegment segment) { if (splitter.Collinear(segment)) { HandleCollinearSegment(splitter, segment); } else if (splitter.OnRight(segment.Start)) { States.RightSegments.Add(segment); } else { States.LeftSegments.Add(segment); } }
private int CalculateScore(BspSegment splitter) { SplitWeights splitWeights = bspConfig.SplitWeights; int score = 0; if (!IsAxisAligned(splitter)) { score += splitWeights.NotAxisAlignedScore; } int splitCount = 0; int linesOnLeft = 0; int linesOnRight = 0; foreach (BspSegment segment in States.Segments) { if (ReferenceEquals(segment, splitter)) { continue; } if (splitter.Parallel(segment)) { if (!splitter.Collinear(segment)) { if (IsEffectivelyRightOfSplitter(splitter, segment)) { linesOnRight++; } else { linesOnLeft++; } } continue; } bool intersects = segment.IntersectionAsLine(splitter, out double tSegment); Debug.Assert(intersects, "Non-parallel lines for split calculations must intersect"); double nearestDistance = CalculateDistanceToNearestEndpoint(segment, tSegment); if (tSegment.InNormalRange()) { if (SplitOccursAtEndpoint(nearestDistance)) { if (IsEffectivelyRightOfSplitter(splitter, segment)) { linesOnRight++; } else { linesOnLeft++; } } else { splitCount++; } } else if (IsEffectivelyRightOfSplitter(splitter, segment)) { linesOnRight++; } else { linesOnLeft++; } // Even though we may have missed, we want to see how close it // was to the splitter. If we pick something like t = 1.0001, // that's very close to the line and will result in likely a // very small seg being generated later on, so avoid this. if (IntersectionNearButNotAtEndpoint(nearestDistance)) { score += splitWeights.NearEndpointSplitScore; } } score += Math.Abs(linesOnLeft - linesOnRight) * splitWeights.LeftRightSplitImbalanceScore; // We do not want to select a splitter that is on the edge of the // map and has no intersections. The only cases for this are if we // pick an edge on the outside hull of the map (which we do not // want as a splitter ever unless it splits something) or a // degenerate/convex hull which we don't care about as those // shapes should never be passed into this function. Therefore, if // it's zero or more collinear traversals with no partitions, that // is always the worst case. if (NoSplitsAndLinesAllOnOneSide(splitCount, linesOnLeft, linesOnRight)) { score = int.MaxValue; } else { score += splitCount * splitWeights.SplitScoreFactor; } return(score); }