/// <summary>
        /// This method uses a different method to the Monotone Chain convex hull
        /// Instead of storing the vertices of the polygon in lists
        /// The vertices are stored as doubly linked lists
        /// </summary>
        private static Polygon RecursiveSolve(Polygon points, bool stepThrough = false)
        {
            //If there are few enough points to warrant the Graham Scan algorithm
            if (points.Count() <= MinimumSize)
            {
                return Polygon.Get(ConvexHull.Solve(points.Convert()));
            }

            //Sort the points by x value and then by y value
            var sortedPoints = PolygonManipulation.SortLexographically(points.Convert());

            //Split points into two sets
            var a = new List<Point2D>();
            var b = new List<Point2D>();

            a.AddRange(sortedPoints.Take(sortedPoints.Count()/2));
            b.AddRange(sortedPoints.Skip(sortedPoints.Count()/2).Take(sortedPoints.Count() - sortedPoints.Count()/2));

            //Compute the convex hulls of a and b recursively
            var polyA = RecursiveSolve(Polygon.Get(a), stepThrough);
            var polyB = RecursiveSolve(Polygon.Get(b), stepThrough);

            //Merge the convex hulls together
            return Merge(polyA, polyB, stepThrough);
        }
        /// <summary>
        /// Merges two convex hulls into one convex hull
        /// Finds upper and lower tangents and removes the points in between
        /// </summary>
        private static Polygon Merge(Polygon polygonA, Polygon polygonB, Boolean stepThrough)
        {
            //Since a lot of functions require polygons of type List<Point2D>
            //Convert them here to save time converting lots later on
            var newPolygonA = PolygonManipulation.SortLexographically(polygonA.Convert());
            var newPolygonB = PolygonManipulation.SortLexographically(polygonB.Convert());

            //Get the rightmost point of polygon A and the leftmost point of polygon B
            var tangentPointA = GetRightmostPoint(newPolygonA);
            var tangentPointB = GetLeftmostPoint(newPolygonB);

            //Find lower tangent
            //While Tangent = tangentPointA -> tangentPointB is not a lower tangent to both A and B
            while (!(IsLowerTangent(newPolygonA, tangentPointA, tangentPointB) && IsLowerTangent(newPolygonB, tangentPointB,tangentPointA)))
            {
                //While Tangent = tangentPointA -> tangentPointB is not a lower tangent to A
                while (!IsLowerTangent(newPolygonA, tangentPointA,tangentPointB))
                {
                    //Move counter clockwise
                    tangentPointA = PolygonManipulation.GetNextPoint(newPolygonA, tangentPointA);
                }

                //While Tangent = tangentPointA -> tangentPointB is not a lower tangent to B
                while (!IsLowerTangent(newPolygonB, tangentPointB,tangentPointA))
                {
                    //Move clockwise
                    tangentPointB = PolygonManipulation.GetPreviousPoint(newPolygonB, tangentPointB);
                }
            }

            //Get the lower tangent
            Vector2D lowerTangent = new Vector2D(tangentPointA, tangentPointB);

            //Reset the tangent points
            tangentPointA = GetRightmostPoint(newPolygonA);
            tangentPointB = GetLeftmostPoint(newPolygonB);

            //While Tangent = tangentPointA -> tangentPointB is not an upper tangent to both A and B
            while (!IsUpperTangent(newPolygonA, tangentPointA, tangentPointB) || !(IsUpperTangent(newPolygonB, tangentPointB, tangentPointA)))
            {
                //While Tangent = tangentPointA -> tangentPointB is not an upper tangent to A
                while (!IsUpperTangent(newPolygonA, tangentPointA, tangentPointB))
                {
                    //Move counter clockwise
                    tangentPointA = PolygonManipulation.GetPreviousPoint(newPolygonA, tangentPointA);
                }

                //While Tangent = tangentPointA -> tangentPointB is not an upper tangent to B
                while (!IsUpperTangent(newPolygonB, tangentPointB, tangentPointA))
                {
                    //Move clockwise
                    tangentPointB = PolygonManipulation.GetNextPoint(newPolygonB, tangentPointB);
                }
            }

            //Get the upper tangent
            Vector2D upperTangent = new Vector2D(tangentPointA, tangentPointB);

            //Draw tangents if in step through mode
            if (stepThrough)
            {
                //Convert the polygons into a format for drawing
                var listPolygonA = polygonA.Convert();
                var listPolygonB = polygonB.Convert();

                //If the polygons have more than two points, fill them in
                if (listPolygonA.Count > 2)
                {
                    GraphicalUserInterface.DrawPolygon(listPolygonA, true, XOffset, YOffset, new System.Drawing.SolidBrush(System.Drawing.Color.Coral));
                    GraphicalUserInterface.DrawPolygon(polygonB.Convert(), true, XOffset, YOffset);
                }

                GraphicalUserInterface.DrawPolygon(listPolygonA, false, XOffset, YOffset, new System.Drawing.SolidBrush(System.Drawing.Color.Coral));
                GraphicalUserInterface.DrawPolygon(polygonB.Convert(), false, XOffset, YOffset);
                GraphicalUserInterface.GraphicsObject.DrawLine(new System.Drawing.Pen(System.Drawing.Color.Blue) { Width = 4 },
                                                               lowerTangent.Start.Convert(XOffset, YOffset, GraphicalUserInterface.SizeMultiplier),
                                                               lowerTangent.Target.Convert(XOffset, YOffset, GraphicalUserInterface.SizeMultiplier));
                GraphicalUserInterface.GraphicsObject.DrawLine(new System.Drawing.Pen(System.Drawing.Color.Black) { Width = 4 },
                                                               upperTangent.Start.Convert(XOffset, YOffset, GraphicalUserInterface.SizeMultiplier),
                                                               upperTangent.Target.Convert(XOffset, YOffset, GraphicalUserInterface.SizeMultiplier));

                //Wait for the user to enter a key into the console to continue
                Console.ReadKey();
            }

            //Wire together the polygons by tangent
            return Wire(polygonA, polygonB, lowerTangent, upperTangent);
        }