/// <summary>
        /// Updates the extrusion with the given <see cref="_discretization"/> and <see cref="Extrusion"/> values.
        /// Updates the <see cref="MeshFilter"/> component with the resulting Mesh.
        /// </summary>
        public void UpdateExtrusion()
        {
            if (_meshFilter == null)
            {
                _meshFilter = GetComponent <MeshFilter>();
            }

            if (_meshRenderer == null)
            {
                _meshRenderer = GetComponent <MeshRenderer>();
            }

            bool doExtrusion = Math.Abs(_extrusion) > ExtrusionNumericalPrecision.MinimumExtrusionDistanceExclusive;

            if (doExtrusion)
            {
                try
                {
                    _lineExtrusionConfiguration = GetLineExtrusionConfiguration(_extrusion);
                    _extrusionResults           = SegmentedLineExtrusionFromIntersection.ExtrudeSegmentedLineBothDirections(this, _lineExtrusionConfiguration);
                    var linePointsWithUVs        = LineSegmentation.GetLinePointsUV(this);
                    var segmentwiseLinePointList = new SegmentwiseLinePointListUV(linePointsWithUVs);
                    _extrudedMesh = ExtrusionTriangulator2D.TriangulatePolygon(_extrusionResults, segmentwiseLinePointList, _lineExtrusionConfiguration);
                    var verts = _extrudedMesh.vertices;
                    for (int i = 0; i < verts.Length; i++)
                    {
                        verts[i] = transform.InverseTransformPoint(verts[i]);
                    }
                    _extrudedMesh.vertices = verts;
                    _meshFilter.mesh       = _extrudedMesh;
                    bool singleContour = _extrusionResults.Contours.Count <= 1;
                    _meshRenderer.material = singleContour ? _singleContourMaterial : _multipleContourMaterial;
                    (singleContour ? OnSingleContourExtrusionUpdated : OnMultipleContourExtrusionUpdated).Invoke();
                }
                catch (Exception e)
                {
                    Debug.LogWarning(string.Format("Error in extrusion of amount {0}: {1}\n{2}.", _extrusion, e.Message, e.StackTrace));
                    _extrudedMesh    = new Mesh();
                    _meshFilter.mesh = _extrudedMesh;
                }
                finally
                {
                }
            }
            else
            {
                _extrudedMesh    = new Mesh();
                _meshFilter.mesh = _extrudedMesh;
            }
        }
        /// <summary>
        /// Return <see cref="LineExtrusionResults"/> containing contiguous lines of extruded points.
        /// </summary>
        /// <param name="originalLine">The line points to be extruded.</param>
        /// <param name="lineExtrusionConfiguration">The extrusion configuration.</param>
        public static LineExtrusionResults ExtrudeSegmentedLineBothDirections(ILineSegmentation originalLine, LineExtrusionConfiguration lineExtrusionConfiguration)
        {
            var originalLinePointsUV = LineSegmentation.GetLinePointsUV(originalLine);

            LineExtrusionResults results;

            if (originalLinePointsUV.Count >= 2)
            {
                var extrudedSubspaceTotal = SegmentedLineExtrusionFromSegments.GetExtrudedSubspaceAllSides(originalLinePointsUV, lineExtrusionConfiguration.ExtrusionAmount);

                results = GetExtrudedLines(originalLinePointsUV, extrudedSubspaceTotal, lineExtrusionConfiguration);
            }
            else
            {
                results = LineExtrusionResults.Empty;
            }

            return(results);
        }
        /// <summary> Draw scene GUI for the spline and extrusion. </summary>
        protected override void OnSceneGUI()
        {
            base.OnSceneGUI();

            var bezierSpline2D = target as BezierSpline2DSegmentable;
            var segmentedLine  = LineSegmentation.GetLinePointsUV(bezierSpline2D);

            bool draw = true;

            if (draw)
            {
                Handles.color = Color.grey;
                for (int i = 0; i < segmentedLine.Count - 1; i++)
                {
                    var p0 = segmentedLine[i].Point;
                    var p1 = segmentedLine[i + 1].Point;
                    Handles.DrawLine(p0, p1);
                    Handles.RectangleHandleCap(-1, p0, Quaternion.identity, 0.001f, EventType.Repaint);
                }


                var extrudedSegmentContours = bezierSpline2D.ExtrusionResults.Contours;

                var colors = new List <Color>()
                {
                    Color.red, Color.yellow, Color.blue, Color.magenta, Color.cyan, Color.green, Color.grey,
                    Color.red * 0.5f, Color.yellow * 0.5f, Color.blue * 0.5f, Color.magenta * 0.5f, Color.cyan * 0.5f, Color.green * 0.5f, Color.grey * 0.5f,
                };

                for (int i = 0; i < extrudedSegmentContours.Count; i++)
                {
                    Handles.color = colors[i % colors.Count];
                    var points = extrudedSegmentContours[i];
                    for (int j = 0; j < points.Length - 1; j++)
                    {
                        var p0 = points[j].Vector;
                        var p1 = points[j + 1].Vector;
                        Handles.DrawLine(p0, p1);
                        Handles.RectangleHandleCap(-1, p0, Quaternion.identity, 0.001f, EventType.Repaint);
                    }
                    Handles.RectangleHandleCap(-1, extrudedSegmentContours[i][extrudedSegmentContours[i].Length - 1].Vector, Quaternion.identity, 0.001f, EventType.Repaint);
                }

                var removedColors = new List <Color>()
                {
                    Color.black, Color.blue * 0.25f, Color.green * 0.25f, Color.red * 0.25f,
                };

                var removedContours = bezierSpline2D.ExtrusionResults.RemovedContours;
                for (int i = 0; i < removedContours.Count; i++)
                {
                    Handles.color = removedColors[i % removedColors.Count];
                    var points = removedContours[i];
                    for (int j = 0; j < points.Length - 1; j++)
                    {
                        var p0 = points[j].Vector;
                        var p1 = points[j + 1].Vector;
                        Handles.DrawLine(p0, p1);
                        Handles.RectangleHandleCap(-1, p0, Quaternion.identity, 0.001f, EventType.Repaint);
                    }
                    Handles.RectangleHandleCap(-1, removedContours[i][removedContours[i].Length - 1].Vector, Quaternion.identity, 0.001f, EventType.Repaint);
                }

                bool drawExtrudedOriginal = false;
                if (drawExtrudedOriginal)
                {
                    var extrudedOrig = SegmentedLineExtrusionFromSegments.GetExtrudedSubspaceAllSides(segmentedLine, bezierSpline2D.Extrusion);
                    for (int i = 0; i < extrudedOrig.Count - 1; i++)
                    {
                        float fraction = i / (float)extrudedOrig.Count;
                        Handles.color = (Color.green * fraction + Color.black * (1f - fraction)) * 0.2f;
                        Handles.DrawLine(extrudedOrig[i].Point, extrudedOrig[i + 1].Point);
                        Handles.RectangleHandleCap(-1, extrudedOrig[i].Point, Quaternion.identity, 0.00125f, EventType.Repaint);
                    }
                    Handles.RectangleHandleCap(-1, extrudedOrig[extrudedOrig.Count - 1].Point, Quaternion.identity, 0.00125f, EventType.Repaint);
                }
            }
        }