#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#include<cassert>
#include<iomanip>
#include<complex>
#include<queue>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)
#define EPS (1e-8)
#define all(n) (n).begin(),(n).end()
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

class Point
{
  public:
  double x,y;

  Point(double x = -inf,double y = -inf): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}

  bool operator < (const Point& p) const
  {
    return !equals(x,p.x)?x<p.x:y<p.y;
  }

  bool operator == (const Point& p)const
  {
    return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
  }

};

struct Segment
{
  Point p1,p2;
  Segment(Point p1 = Point(-inf,-inf),Point p2 = Point(-inf,-inf)):p1(p1),p2(p2){}
  bool operator == (const Segment& p)const
  {
    return p.p1 == p1 && p.p2 == p2;
  }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a)
{
  os << "(" << a.x << "," << a.y << ")";
}

ostream& operator << (ostream& os,const Segment& a)
{
  os << "( " << a.p1 << " , " << a.p2 << " )";
}

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

int ccw(Point p0,Point p1,Point p2)
{
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}
Point crosspoint(Line l, Line m) {
  double A = cross(l.p2 - l.p1, m.p2 - m.p1);
  double B = cross(l.p2 - l.p1, l.p2 - m.p1);
  if (abs(A) < EPS && abs(B) < EPS) return m.p1; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m.p1 +   (m.p2 - m.p1) * (B / A);
}



// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-|

struct SP
{
  Segment seg;
  int type;// type 0 -> Point, type 1 -> Segment;
  SP(Segment seg = Segment(),int type=inf):seg(seg),type(type){}
};

struct Edge
{
  int from,to;
  double cost;
  Edge(int from=inf,int to=inf,double cost=inf):from(from),to(to),cost(cost){}
  bool operator < (const Edge& a)const
  {
    return cost < a.cost;
  }
};

typedef vector<Edge> vE;
typedef vector<vE> vvE;

int N;
vector<SP> vec;


vector<vector<Edge> > segmentArrangementVer1(vector<Segment> vs,vector<Point> &ps)
{

  rep(i,vs.size())
    REP(j,i+1,vs.size())
      if(intersectSS(vs[i],vs[j]))
        ps.push_back(Point(crosspoint(vs[i],vs[j])));

  //
  ps.push_back(vec[0].seg.p1);
  ps.push_back(vec[1].seg.p2);
  //

  sort(all(ps));  
  ps.erase(unique(all(ps)),ps.end());

  vector<vector<Edge> > ret(ps.size());

  for(int i=0;i<vs.size();i++)
    {
      vector<pair<double,int> > list;
      rep(j,ps.size())
	if(intersectSP(vs[i],ps[j]))
	  list.push_back(pair<double,int>(norm(vs[i].p1-ps[j]),j));

      sort(all(list));

      //for(int j=0;j<list.size()-1;++j) is not good
      for(int j=0;j+1<list.size();++j)
	{
	  int from = list[j].second, to = list[j+1].second;
	  double cost = abs(ps[from]-ps[to]);
	  ret[from].push_back(Edge(from,to,cost));
	  ret[to].push_back(Edge(to,from,cost));
	}
    }  
  return ret;
}

void toSegOnly(vector<Segment> &vs)
{
  rep(i,2)
    {
      REP(j,2,2+N)
	{
	  assert(vec[i].seg.p1 == vec[i].seg.p2);
	  Point prj = projection(vec[j].seg,vec[i].seg.p1);
	  //cout << i << "," << j << " : " << prj << endl;
	  if(intersectSP(vec[j].seg,prj))
	    {
	      if(vec[i].seg.p1 == prj)continue;
	      //cout << vec[i].seg.p1 << " intersect : " << i << " and " << j << " " << prj << endl; 
	      Point e = vec[i].seg.p1 - prj;
	      //cout << "fe : " << e << endl;
	      e = (e/abs(e))*1000;
	      //cout << "e : " << e << endl;
	      vs.push_back(Segment(vec[i].seg.p1-e,prj+e));
	    }
	}
    }
  /*
  cout << "VS =----------------- " << vs.size() << endl;
  rep(i,vs.size())
    cout << vs[i] << endl;
  */
  REP(j,2,2+N)
    {
      Segment seg = Segment(vec[j].seg.p1 - vec[j].seg.p2,vec[j].seg.p2 - vec[j].seg.p2);
      Point rig = rotate(seg.p1,toRad(90.0));
      rig = (rig/abs(rig))*1000;
      vs.push_back(Segment(vec[j].seg.p1-rig,vec[j].seg.p1+rig));
      vs.push_back(Segment(vec[j].seg.p2-rig,vec[j].seg.p2+rig));
    }
}

//segment merge--------
bool merge_if_able(Segment &s, Segment t) {
  if (abs(cross(s.p2-s.p1, t.p2-t.p1)) > EPS) return false;
  if (ccw(s.p1, t.p1, s.p2) == +1 ||
      ccw(s.p1, t.p1, s.p2) == -1) return false; // not on the same line
  if (ccw(s.p1, s.p2, t.p1) == -2 ||
      ccw(t.p1, t.p2, s.p1) == -2) return false; // separated
  s = Segment(min(s.p1, t.p1), max(s.p2, t.p2));
  return true;
}
void merge_segments(vector<Segment>& segs) {
  for (int i = 0; i < segs.size(); ++i)
    if (segs[i].p2 < segs[i].p1)
      swap(segs[i].p2, segs[i].p1);
  for (int i = 0; i < segs.size(); ++i)
    for (int j = i+1; j < segs.size(); ++j)
      if (merge_if_able(segs[i], segs[j]))
        segs[j--] = segs.back(), segs.pop_back();
}
// -------------------

struct Pox
{
  int cur;
  double cost;
  Pox(int cur=inf,double cost=inf):cur(cur),cost(cost){}
  bool operator < (const Pox& a)const
  {
    return cost > a.cost;
  }
};

void dijkstra(vvE &G,int st,int ed)
{
  int n = G.size();
  double mincost[n];
  rep(i,n)mincost[i] = inf;
  mincost[st] = 0;
  priority_queue<Pox> Q;
  Q.push(Pox(st,0));

  while(!Q.empty())
    {
      Pox pox = Q.top(); Q.pop();

      if(pox.cur == ed)
	{
	  cout << setiosflags(ios::fixed) << setprecision(5) << pox.cost << endl;
	  return;
	}

      rep(i,G[pox.cur].size())
	{
	  int next = G[pox.cur][i].to;
	  double cost = G[pox.cur][i].cost;
	  if(!equals(mincost[next],pox.cost+cost) && mincost[next] > pox.cost + cost)
	    {
	      mincost[next] = pox.cost + cost;
	      Q.push(Pox(next,pox.cost+cost));
	    }
	}

    }
  cout << "Impossible" << endl;
}

void compute()
{
  vector<Segment> vs;
  toSegOnly(vs);

  /*
  cout << "vs------bef" << endl;
  rep(i,vs.size())
    {
      cout << vs[i] << endl;
    }
  
  
  rep(i,vs.size())
    if(!equals(vs[i].p1.x,vs[i].p2.x) && vs[i].p1.x > vs[i].p2.x)
      swap(vs[i].p1,vs[i].p2);
  */
  merge_segments(vs);  
  /*
  cout << "vs------aft" << endl;
  rep(i,vs.size())
    {
      cout << vs[i] << endl;
    }
  */

  vector<Point> ps;
  vvE G = segmentArrangementVer1(vs,ps);

  int st_index,ed_index;
  rep(i,ps.size())
    {
      //cout << "ps[" << i << "] = "<< ps[i] << endl;
      if(ps[i] == vec[0].seg.p1)st_index = i;
      if(ps[i] == vec[1].seg.p1)ed_index = i;
    }

  //cout << "st = " << st_index << endl;
  //cout << "ed = " << ed_index << endl;

  /*
  cout << "G-----" << endl;
  rep(i,G.size())
    {
      cout << "node " << i << endl;
      rep(j,G[i].size())
	{
	  cout << "(" << G[i][j].from << "," << G[i][j].to << "," << G[i][j].cost << ") ";
	}
      cout << endl;
    }
  */
  dijkstra(G,st_index,ed_index);
   
}

int main()
{
  int CNT = 1;
  while(cin >> N,N)
    {
      vec.clear();
      vec.resize(N+2);
      double x,y;
      rep(i,2)
	{
	  cin >> x >> y;
	  vec[i].seg.p1 = vec[i].seg.p2 = Point(x,y);
	  vec[i].type = 0;
	}
      rep(i,N)
	cin >> vec[2+i].seg.p1.x >> vec[2+i].seg.p1.y >> vec[2+i].seg.p2.x >> vec[2+i].seg.p2.y;
      cout << "Case " << CNT++ << ": ";
      compute();
    }
  return 0;
}

Measured memory_bytes: 4500