using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

namespace CsharpSolution
{

    #region Point

    public sealed class Point : IEquatable<Point>
    {
        public int X, Y;

        #region .ctors

        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }

        public Point() : this(0, 0)
        {
        }

        public Point(Point p) : this(p.X, p.Y)
        {
        }

        #endregion

        #region Overloaded operators

        public static Point operator +(Point a, Point b)
        {
            return new Point(a.X + b.X, a.Y + b.Y);
        }

        public static Point operator -(Point a, Point b)
        {
            return new Point(a.X - b.X, a.Y - b.Y);
        }

        /// <summary>
        /// Scalar product
        /// </summary>
        public static int operator ^(Point a, Point b)
        {
            return a.X*b.X + a.Y*b.Y;
        }

        /// <summary>
        /// Skew product
        /// </summary>
        public static int operator *(Point a, Point b)
        {
            return a.X*b.Y - a.Y*b.X;
        }

        public static bool operator ==(Point a, Point b)
        {
            return a.X == b.X && a.Y == b.Y;
        }

        public static bool operator !=(Point a, Point b)
        {
            return !(a == b);
        }

        #endregion

        #region IEquatable<Point> Members

        public bool Equals(Point point)
        {
            if (point == null) return false;
            return this == point;
        }

        #endregion

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj)) return true;
            return Equals(obj as Point);
        }

        public override int GetHashCode()
        {
            return X + 29*Y;
        }
    }

    #endregion

    #region Segment

    public sealed class Segment
    {
        public Point P1, P2;

        #region .ctors

        public Segment(Point p1, Point p2)
        {
            P1 = new Point(p1);
            P2 = new Point(p2);
        }

        public Segment() : this(new Point(), new Point())
        {
        }

        public Segment(Segment s) : this(s.P1, s.P2)
        {
        }

        #endregion

        #region Properties

        public int Left
        {
            get { return Math.Min(P1.X, P2.X); }
        }

        public int Right
        {
            get { return Math.Max(P1.X, P2.X); }
        }

        public int Top
        {
            get { return Math.Max(P1.Y, P2.Y); }
        }

        public int Bottom
        {
            get { return Math.Min(P1.Y, P2.Y); }
        }

        #endregion

        #region Methods

        public bool IsInside(Point p, bool includeEndPoints)
        {
            if (p == P1 || p == P2) return includeEndPoints;
            if ((p - P1)*(p - P2) != 0) return false;
            return p.X >= Left && p.X <= Right && p.Y >= Bottom && p.Y <= Top;
        }

        public bool IsCrossing(Segment s, bool includeEndPoints)
        {
            if (Left > s.Right || Right < s.Left || Top < s.Bottom || Bottom > s.Top) return false;
            int sign1 = Math.Sign((P2 - P1)*(s.P1 - P1)), sign2 = Math.Sign((P2 - P1)*(s.P2 - P1));
            if (sign1 == 0 && sign2 == 0)
            {
                return false;
            }
            if (sign1*sign2 == 0) return includeEndPoints;
            if (sign1*sign2 > 0) return false;
            sign1 = Math.Sign((s.P2 - s.P1)*(P1 - s.P1));
            sign2 = Math.Sign((s.P2 - s.P1)*(P2 - s.P1));
            if (sign1*sign2 == 0) return includeEndPoints;
            return (sign1*sign2 < 0);
        }

        #endregion
    }

    #endregion

    public sealed class Program
    {
        private const double INF = 1e9;
        private const int MAXN = 100;
        private const int MAXX = 1000;

        private static void Assert(bool condition)
        {
            if (!condition)
            {
                throw new Exception("Assertion failed");
            }
        }

        private static void CheckPoint(Point p)
        {
            Assert(Math.Abs(p.X) <= MAXX && Math.Abs(p.Y) <= MAXX);
        }

        private static void CheckSegment(Segment s)
        {
            CheckPoint(s.P1);
            CheckPoint(s.P2);
        }

        private static double Distance(Point p1, Point p2, IEnumerable<Segment> segments)
        {
            Segment path = new Segment(p1, p2);
            foreach (Segment segment in segments)
            {
                if (segment.IsCrossing(path, false)) return INF;
            }
            return Math.Sqrt((p1.X - p2.X)*(p1.X - p2.X) + (p1.Y - p2.Y)*(p1.Y - p2.Y));
        }

        public static double Solve(IList<Segment> segments, Point from, Point to)
        {
            int n = segments.Count*2 + 2;
            double[,] c = new double[n,n];

            List<Point> points = new List<Point>();
            points.Add(from); points.Add(to);

            foreach (Segment segment in segments)
            {
                points.Add(segment.P1);
                points.Add(segment.P2);
            }

            for (int i = 0; i < n; ++i )
                for (int j = i+1; j < n; ++j)
                {
                    c[i, j] = Distance(points[i], points[j],segments);
                    c[j, i] = c[i, j];
                }

            for (int k = 0; k < n; ++k)
                for (int i = 0; i < n; ++i)
                    for (int j = 0; j < n; ++j)
                        c[i, j] = Math.Min(c[i, j], c[i, k] + c[k, j]);

            return c[0, 1] < INF ? c[0, 1] : -1;
        }

        private static void CheckInput(IList<Segment> segments, Point from, Point to)
        {
            Assert(segments.Count >= 0 && segments.Count <= MAXN);

            foreach (Segment segment in segments)
            {
                CheckSegment(segment);
            }

            CheckPoint(from);
            CheckPoint(to);

            foreach (Segment segment in segments)
            {
                Assert(!segment.IsInside(from, true) && !segment.IsInside(to, true));
            }

            for(int i=0; i<segments.Count; ++i)
                for (int j = 0; j < segments.Count; ++j) if (i!=j)
                    Assert(!segments[j].IsInside(segments[i].P1, true) && !segments[j].IsInside(segments[i].P2, true));
        }

        public static void Main()
        {
           // using (StreamReader input = new StreamReader("robot.in"))
            {
                int n;
                List<Segment> segments = new List<Segment>();
                Point A, B;

                string[] data;
                string tmp = Console.ReadLine();
                n = int.Parse(tmp);

                for (int i = 0; i < n; ++i)
                {
                    data = Console.ReadLine().Split(' ');
                    Assert(data.Length == 4);
                    segments.Add(
                        new Segment(new Point(int.Parse(data[0]), int.Parse(data[1])),
                                    new Point(int.Parse(data[2]), int.Parse(data[3]))));
                }

                data = Console.ReadLine().Split(' ');
                Assert(data.Length == 2);
                A = new Point(int.Parse(data[0]), int.Parse(data[1]));

                data = Console.ReadLine().Split(' ');
                Assert(data.Length == 2);
                B = new Point(int.Parse(data[0]), int.Parse(data[1]));

                CheckInput(segments, A, B);

                //using (StreamWriter output = new StreamWriter("robot.out"))
                {
                    NumberFormatInfo nf = new NumberFormatInfo();
                    nf.NumberDecimalSeparator = ".";
                    Console.Write(Solve(segments, A, B).ToString("0.####", nf));
                }
            }
        }
    }
}