/// <summary>
        /// Determine if a chunk of extruded points is too close to a line of points, determined by comparing the extruded point whose parameter is furthest from any intersection points.
        /// </summary>
        /// <param name="extrudedContinuousChunk">Chunk of extruded points between two intersection endpoints.</param>
        /// <param name="linePoints">Points on the line from which to determine distance.</param>
        /// <param name="intersectionPoints">All intersection points between extruded segments.</param>
        /// <param name="extrusionAmount">The extrusion amount.</param>
        private static bool IsExtractedContinuousChunkooClose_DeterminedFromFurthestParameter(ChunkBetweenIntersections extrudedContinuousChunk, SegmentwiseLinePointListUV linePoints, IList <IntersectionPoint> intersectionPoints, float extrusionAmount)
        {
            bool tooClose;

            if (extrudedContinuousChunk.ExtrudedPoints.Count > 0)
            {
                var pointToCheck = PointOfLargestParameterDifference(extrudedContinuousChunk.ExtrudedPoints, intersectionPoints);
                tooClose = SegmentedLineUtil.IsCloserThanExtrusionDistance_Segmentwise(pointToCheck, linePoints, extrusionAmount);
            }
            else
            {
                tooClose = IsIntersectionPointChunkSegmentCloserThanExtrusionDistance(extrudedContinuousChunk.StartIntersection, extrudedContinuousChunk.EndIntersection, linePoints, extrusionAmount);
            }
            return(tooClose);
        }
        /// <summary>
        /// Triangulate a line based on a single closed contour of extruded points, by creating quads connecting points of the the same u-parameter on opposite sides of the original line.
        /// </summary>
        /// <param name="lineExtrusionResults">Line extrusion results</param>
        /// <param name="extrusionConfiguration">The extrusion configuration parameters</param>
        private static Mesh TriangulateLine_ConnectExtrudedPointsOfSameUParameter(LineExtrusionResults lineExtrusionResults, LineExtrusionConfiguration extrusionConfiguration)
        {
            var mesh = new Mesh();

            var originalLinePointsList = lineExtrusionResults.OriginalLinePointList;
            //NB Setting closest original segment index is not even needed in this implementation, but it's a reasonable choice to sent as the second half of the addition uv we're sending.
            var extrusionAmountAbs              = Mathf.Abs(extrusionConfiguration.ExtrusionAmount);
            var connectedSegmentsResults        = lineExtrusionResults.ConnectedSegmentsExtrusionResults;
            var contourConnectedSegmentsResults = connectedSegmentsResults.SegmentwiseCoverageOfSingleContour;

            if (contourConnectedSegmentsResults != null)
            {
                var firstPoint = contourConnectedSegmentsResults.FirstPoint;
                var lastPoint  = contourConnectedSegmentsResults.LastPoint;
                var increasingSegmentPoints = contourConnectedSegmentsResults.IncreasingPortionSegmentPoints;
                var decreasingSegmentPoints = contourConnectedSegmentsResults.DecreasingPortionSegmentPoints;

                if (increasingSegmentPoints.Count == decreasingSegmentPoints.Count && increasingSegmentPoints.Count >= 1)
                {
                    int       numInBetweenUParameters = decreasingSegmentPoints.Count;
                    Vector3[] vertices  = new Vector3[numInBetweenUParameters * 2 + 2];
                    Vector2[] uvs       = new Vector2[numInBetweenUParameters * 2 + 2];
                    Vector2[] indexUvs  = new Vector2[numInBetweenUParameters * 2 + 2];
                    int[]     trindices = new int[(numInBetweenUParameters - 1) * 6 + 6];

                    vertices[0] = firstPoint.Vector;
                    uvs[0]      = firstPoint.UV;
                    int closestOriginalSegmentIndex = SegmentedLineUtil.ClosestIndexAlongSegmentwiseLine(firstPoint.Vector, originalLinePointsList, extrusionAmountAbs);
                    indexUvs[0] = new Vector2(-1, closestOriginalSegmentIndex);
                    vertices[numInBetweenUParameters * 2 + 1] = lastPoint.Vector;
                    uvs[numInBetweenUParameters * 2 + 1]      = lastPoint.UV;
                    closestOriginalSegmentIndex = SegmentedLineUtil.ClosestIndexAlongSegmentwiseLine(lastPoint.Vector, originalLinePointsList, extrusionAmountAbs);
                    indexUvs[numInBetweenUParameters * 2 + 1] = new Vector2(numInBetweenUParameters, closestOriginalSegmentIndex);

                    for (int i = 0; i < numInBetweenUParameters; i++)
                    {
                        var increasingPoint = increasingSegmentPoints[i];
                        var decreasingPoint = decreasingSegmentPoints[i];

                        vertices[i * 2 + 1]         = increasingPoint.Vector;
                        uvs[i * 2 + 1]              = increasingPoint.UV;
                        closestOriginalSegmentIndex = SegmentedLineUtil.ClosestIndexAlongSegmentwiseLine(increasingPoint.Vector, originalLinePointsList, extrusionAmountAbs);
                        indexUvs[i * 2 + 1]         = new Vector2(i, closestOriginalSegmentIndex);

                        vertices[i * 2 + 2]         = decreasingPoint.Vector;
                        uvs[i * 2 + 2]              = decreasingPoint.UV;
                        closestOriginalSegmentIndex = SegmentedLineUtil.ClosestIndexAlongSegmentwiseLine(decreasingPoint.Vector, originalLinePointsList, extrusionAmountAbs);
                        indexUvs[i * 2 + 2]         = new Vector2(i, closestOriginalSegmentIndex);
                    }

                    //NB This order of triangle indices is consistent with our direction of extrusion points winding around the original line
                    trindices[0] = 0;
                    trindices[1] = 1;
                    trindices[2] = 2;
                    trindices[numInBetweenUParameters * 6 - 3] = numInBetweenUParameters * 2 + 0;
                    trindices[numInBetweenUParameters * 6 - 2] = numInBetweenUParameters * 2 - 1;
                    trindices[numInBetweenUParameters * 6 - 1] = numInBetweenUParameters * 2 + 1;

                    for (int j = 0; j < numInBetweenUParameters - 1; j++)
                    {
                        trindices[3 + j * 6 + 0] = 1 + j * 2 + 1;
                        trindices[3 + j * 6 + 1] = 1 + j * 2 + 0;
                        trindices[3 + j * 6 + 2] = 1 + j * 2 + 2;
                        trindices[3 + j * 6 + 3] = 1 + j * 2 + 2;
                        trindices[3 + j * 6 + 4] = 1 + j * 2 + 3;
                        trindices[3 + j * 6 + 5] = 1 + j * 2 + 1;
                    }

                    mesh.vertices  = vertices;
                    mesh.uv        = uvs;
                    mesh.triangles = trindices;
                    mesh.uv4       = indexUvs;
                }
                else
                {
                    Debug.LogError("Not enough connected extruded points to create mesh.");
                }
            }
            else
            {
                Debug.LogError("Single contour connected segments results are not calculated.");
            }

            return(mesh);
        }