Models the intersection of two LineSegment2 instances.
        private static void Render(IEnumerable<LineSegment2> allLineSegments, Intersection[] intersections)
        {
            var allPoints = allLineSegments.SelectMany(l => new[] { l.End1, l.End2 }).Concat(intersections.Select(i => i.Point)).ToList();

            var width = (int)Math.Ceiling(allPoints.Max(p => p.X));
            var height = (int)Math.Ceiling(allPoints.Max(p => p.Y));

            var linePen = new Pen(Color.White, 5);
            var selectedLinePen = new Pen(Color.Yellow, 8);
            var quadrilateralPen = new Pen(Color.Red, 5);

            var form = new Form { ClientSize = new Size(width, height) };
            var bitmap = new Bitmap(width, height);
            using (var g = Graphics.FromImage(bitmap))
            {
                g.Clear(Color.Black);

                foreach (var line in _sampleLineSegments)
                    g.DrawLine(linePen, (float)line.End1.X, (float)line.End1.Y, (float)line.End2.X, (float)line.End2.Y);
                foreach (var line in intersections.SelectMany(i => new[] { i.Line1, i.Line2 }).Distinct())
                    g.DrawLine(selectedLinePen, (float)line.End1.X, (float)line.End1.Y, (float)line.End2.X, (float)line.End2.Y);
                g.DrawPolygon(quadrilateralPen, intersections.Select(i => new PointF((float)i.Point.X, (float)i.Point.Y)).ToArray());
            }

            form.Controls.Add(new PictureBox { Image = bitmap, Width = width, Height = height });
            form.ShowDialog();
        }
        private static double CalculateError(Intersection[] intersections)
        {
            var distanceError = intersections.Sum(
                intersection =>
                {
                    Func<double, double> calcDistancePenalty = d =>
                    {
                        if (d > 0 && d < 1)
                        {
                            // Itersection within the line segment is a bad sign, so penalise for it, proportionally
                            return -Math.Log(d > 0.5 ? 1 - d : d);
                        }
                        return 0;
                    };

                    return calcDistancePenalty(intersection.Distance1) + calcDistancePenalty(intersection.Distance2);
                }
                );

            var angles = new[]
                {
                    GetAcuteAngleBetweenPoints(intersections[0].Point, intersections[1].Point, intersections[2].Point),
                    GetAcuteAngleBetweenPoints(intersections[1].Point, intersections[2].Point, intersections[3].Point),
                    GetAcuteAngleBetweenPoints(intersections[2].Point, intersections[3].Point, intersections[0].Point),
                    GetAcuteAngleBetweenPoints(intersections[3].Point, intersections[0].Point, intersections[1].Point)
                };

            // Sum of squared errors
            const double piOnTwo = Math.PI/2;
            var angleError = angles.Sum(angle => Math.Pow(piOnTwo - Math.Abs(angle), 2));

            return angleError + distanceError;
        }