/// <summary> /// Compares two <see cref="UParameterIndexAndMonotonicity"/> values by their u parameters. /// </summary> /// <param name="first">The first value</param> /// <param name="second">The second value</param> private static int CompareUParameterIndexAndMonotonicityByUParameter(UParameterIndexAndMonotonicity first, UParameterIndexAndMonotonicity second) { return(first.UParameter.CompareTo(second.UParameter)); }
/// <summary> /// For a contour consisting of one portion monotonically increasing in u-parameter and the other monotonically decreasing, return the <see cref="SingleContourSegmentwiseCoverage"/> /// where there are matching points (at the same u-parameter) on both the increasing and decreasing portions. /// </summary> /// <param name="monotonicIncreasingChunk">Portion of contour with monotonically increasing u-parameters</param> /// <param name="monotonicDecreasingChunk">Portion of contour with monotonically decreasing u-parameters</param> internal static SingleContourSegmentwiseCoverage GetSingleContourSegmentwiseCoverage(ExtrudedContourMonotonicChunk monotonicIncreasingChunk, ExtrudedContourMonotonicChunk monotonicDecreasingChunk) { List <UParameterIndexAndMonotonicity> allContourPointUParameters = new List <UParameterIndexAndMonotonicity>(); List <Vector2WithUV> monotonicIncreasingPoints = monotonicIncreasingChunk.Points; List <Vector2WithUV> monotonicDecreasingPoints = monotonicDecreasingChunk.Points; //Skip the last point in each chunk so as to not double-count the 'endpoints' of min/max u-parameter for (int i = 0; i < monotonicIncreasingPoints.Count - 1; i++) { allContourPointUParameters.Add(new UParameterIndexAndMonotonicity(monotonicIncreasingPoints[i].UV.x, i, true)); } for (int i = 1; i < monotonicDecreasingPoints.Count; i++) { allContourPointUParameters.Add(new UParameterIndexAndMonotonicity(monotonicDecreasingPoints[i].UV.x, i, false)); } allContourPointUParameters.Sort(CompareUParameterIndexAndMonotonicityByUParameter); allContourPointUParameters.RemoveAt(allContourPointUParameters.Count - 1); allContourPointUParameters.RemoveAt(0); int numInBetweenUParameters = allContourPointUParameters.Count; var firstPoint = monotonicIncreasingPoints[0]; var lastPoint = monotonicDecreasingPoints[monotonicDecreasingPoints.Count - 1]; List <Vector2WithUV> increasingChunkPoints = new List <Vector2WithUV>(); List <Vector2WithUV> decreasingChunkPoints = new List <Vector2WithUV>(); for (int i = 0; i < numInBetweenUParameters; i++) { UParameterIndexAndMonotonicity uParameterIndexAndMonotonicity = allContourPointUParameters[i]; ExtrudedContourMonotonicChunk givenMonotonicChunk = uParameterIndexAndMonotonicity.IsMonotonicIncreasing ? monotonicIncreasingChunk : monotonicDecreasingChunk; ExtrudedContourMonotonicChunk otherMonotonicChunk = uParameterIndexAndMonotonicity.IsMonotonicIncreasing ? monotonicDecreasingChunk : monotonicIncreasingChunk; Vector2WithUV givenMonotonicChunkPoint = givenMonotonicChunk.Points[uParameterIndexAndMonotonicity.Index]; Vector2WithUV matchingMonotonicChunkPoint; bool gotMatchingPoint = otherMonotonicChunk.GetClosestPoint(uParameterIndexAndMonotonicity.UParameter, out matchingMonotonicChunkPoint); if (gotMatchingPoint) { var increasingPoint = uParameterIndexAndMonotonicity.IsMonotonicIncreasing ? givenMonotonicChunkPoint : matchingMonotonicChunkPoint; var decreasingPoint = uParameterIndexAndMonotonicity.IsMonotonicIncreasing ? matchingMonotonicChunkPoint : givenMonotonicChunkPoint; increasingChunkPoints.Add(increasingPoint); decreasingChunkPoints.Add(decreasingPoint); } } //Now remove connected segments pairs that are effectively duplicates of a neighbouring segment for (int i = increasingChunkPoints.Count - 1; i > 0; i--) { var increasingPoint = increasingChunkPoints[i]; var decreasingPoint = increasingChunkPoints[i]; var prevIncreasingPoint = increasingChunkPoints[i - 1]; var prevDecreasingPoint = increasingChunkPoints[i - 1]; bool increasingAreClose = ConnectedSegmentPointsAreClose(prevIncreasingPoint, increasingPoint); bool decreasingAreClose = ConnectedSegmentPointsAreClose(prevDecreasingPoint, decreasingPoint); if (increasingAreClose && decreasingAreClose) { increasingChunkPoints.RemoveAt(i); decreasingChunkPoints.RemoveAt(i); } } return(new SingleContourSegmentwiseCoverage(firstPoint, lastPoint, increasingChunkPoints, decreasingChunkPoints)); }