``Eyeball benders" are a popular kind of puzzle in which the reader must identify a common object based on a close- up view of a part of that object. For instance, an image that looks like a regular array of colored cones might be a view of an open box of new crayons. Figure 1 shows an example where the puzzle is on the left and the solution is on the right.
You must verify solutions to a simplified version of the ``eyeball bender" puzzle. You will be given a number of pairs of images, each one a collection of line segments. All line segments will be either horizontal or vertical, and they include their endpoints. Figure 2 shows an example.
You must determine whether the images form a valid pair in which the first image is a magnified view of some portion of the second image. Lines are assumed to have zero thickness in both images. At least one endpoint in the puzzle image of a valid pair must be an endpoint of a line segment in the solution image.
Coordinates describe relative positions and scale within a single image. The coordinates in one image do not necessarily use the same origin or scale as those in the other image. The magnification of the puzzle image relative to the solution image is required to be greater than or equal to 1. For Figure 2, your program should determine that this is a valid puzzle/solution image pair.
Input
The input consists of multiple cases. The input for each case begins with two positive integers M and N, (1M, N50). M is the number of line segments in the puzzle image. N is the number of line segments in the proposed solution image. The following lines contain M + N pairs of points. The first M pairs of points are the endpoints of the line segments in the puzzle image; the remaining N pairs are the endpoints of the line segments in the proposed solution image. The x and y coordinates for each pair satisfy -100x, y100 and are given to at most three decimal places of precision. All input values are separated by white space (blanks or new line characters).
No pair of distinct points in a given image will be closer than .005 to another (relative to the scale of the image) and all segments will have length at least .005. No two horizontal segments overlap and no two vertical segments overlap. However, horizontal segments may intersect vertical segments either internally or at segment endpoints.
The input data for the last case is followed by a line consisting of the integers `0 0'.
Output
For each input case, display the case number (1, 2, ...) followed by the words `valid puzzle' if the proposed solution image matches a closed rectangular sub-region of the puzzle image (including at least one endpoint), magnified by a factor of one or greater, and possibly translated by some amount. Line segments that are not included in the puzzle image will be at least 0.005 distant from the rectangle.
If the match condition fails to hold, print `impossible'. Follow the format of the sample output.
Sample Input
3 12 9 8 7.5 8 1.5 8 1.5 3.5 0 5 9 5 4 2 8 2 5 7 2 7 10 6 8 6 8 7 8 4 1 9 8 9 9 3 7 3 4 10 4 5 4 2 4 4 5 8 5 7 3 6 6 6 0 3 3 3 5 1 5 3 4 12 -50 -5 50 -5 0 10 0 -10 50 5 -50 5 -50 0 50 0 4 2 8 2 5 7 2 7 10 6 8 6 8 7 8 4 1 9 8 9 9 3 7 3 4 10 4 5 4 2 4 4 5 8 5 7 3 6 6 6 0 3 3 3 5 1 5 3 0 0
Sample Output
Case 1: valid puzzle Case 2: impossible
#include<stdio.h>
#include<math.h>
struct line
{
double x1,y1,x2,y2;
};
struct point
{
double x,y;
};
const double delta=1e-6;
bool ok;
int T,n,m,i,j,k;
double scale;
point pL,pS;
line tL;
line L[60],S[60],SN[60];
line in()
{
double tmp;
line t;
scanf("%lf %lf %lf %lf",&t.x1,&t.y1,&t.x2,&t.y2);
if(t.x1>t.x2+delta)
{
tmp=t.x1;
t.x1=t.x2;
t.x2=tmp;
}
if(t.y1>t.y2+delta)
{
tmp=t.y1;
t.y1=t.y2;
t.y2=tmp;
}
return t;
}
bool same(double x,double y)
{
return (y-delta<x && x<y+delta);
}
bool findS(line p)
{
int i;
for(i=0;i<n;i++)
{
if(same(p.x1,p.x2)&&same(L[i].x1,L[i].x2)&&same(p.x1,L[i].x1))
if(L[i].y1<=p.y1&&p.y2<=L[i].y2)
return true;
if(same(p.y1,p.y2)&&same(L[i].y1,L[i].y2)&&same(p.y1,L[i].y1))
if(L[i].x1<=p.x1&&p.x2<=L[i].x2)
return true;
}
return false;
}
bool findL(line p)
{
int i;
for(i=0;i<m;i++)
{
if(same(p.x1,p.x2)&&same(SN[i].x1,SN[i].x2)&&same(p.x1,SN[i].x1))
if(SN[i].y1<=p.y1 && p.y2<=SN[i].y2)
return true;
if(same(p.y1,p.y2)&&same(SN[i].y1,SN[i].y2)&&same(p.y1,SN[i].y1))
if(SN[i].x1<=p.x1&&p.x2<=SN[i].x2)
return true;
}
return false;
}
double dis(double x,double y)
{
return sqrt(x*x+y*y);
}
bool check()
{
double MaxX,MaxY,MinX,MinY;
int i,j,k;
MaxX=MinX=pL.x;
MaxY=MinY=pL.y;
for(i=0;i<m;i++)
{
SN[i].x1=(S[i].x1-pS.x)*scale + pL.x;
SN[i].y1=(S[i].y1-pS.y)*scale + pL.y;
SN[i].x2=(S[i].x2-pS.x)*scale + pL.x;
SN[i].y2=(S[i].y2-pS.y)*scale + pL.y;
if(!findS(SN[i]))
return false;
if(SN[i].x1<MinX)
MinX=SN[i].x1;
if(SN[i].x2>MaxX)
MaxX=SN[i].x2;
if(SN[i].y1<MinY)
MinY=SN[i].y1;
if(SN[i].y2>MaxY)
MaxY=SN[i].y2;
}
for(i=0;i<n;i++)
{
if(same(L[i].x1,L[i].x2))
{
if(L[i].x1>MaxX)
{
if(L[i].y1>MaxY)
{
if(dis(L[i].x1-MaxX,L[i].y1-MaxY)<0.005)
return false;
}
else if( L[i].y2<MinY)
{
if(dis(L[i].x1-MaxX,L[i].y2-MinY)<0.005)
return false;
}
else if(L[i].x1-MaxX<0.005)
return false;
}
else if(L[i].x2<MinX)
{
if(L[i].y1>MaxY)
{
if(dis(L[i].x2-MinX,L[i].y1-MaxY)<0.005)
return false;
}
else if(L[i].y2<MinY)
{
if(dis(L[i].x2-MinX,L[i].y2-MinY)<0.005)
return false;
}
else if(MinX-L[i].x2<0.005)
return false;
}
else
{
if(L[i].y2<MinY-0.005 || L[i].y1>MaxY + 0.005)
continue;
if(L[i].y2<MinY || L[i].y1>MaxY)
return false;
tL=L[i];
if(tL.y1<MinY)
tL.y1=MinY;
if(tL.y2>MaxY)
tL.y2=MaxY;
if(!findL(tL))
return false;
}
}
else
{
if(L[i].y1>MaxY)
{
if(L[i].x1>MaxX)
{
if(dis(L[i].x1-MaxX,L[i].y1-MaxY)<0.005)
return false;
}
else if(L[i].x2<MinX)
{
if(dis(L[i].x2-MinX,L[i].y1-MaxY)<0.005)
return false;
}
else if(L[i].y1-MaxY<0.005)
return false;
}
else if(L[i].y2<MinY)
{
if(L[i].x1>MaxX)
{
if(dis(L[i].x1-MaxX,L[i].y2-MinY)<0.005)
return false;
}
else if(L[i].x2<MinX)
{
if(dis(L[i].x2-MinX,L[i].y2-MinY)<0.005)
return false;
}
else if(MinY-L[i].y2<0.005)
return false;
}
else
{
if(L[i].x2<MinX-0.005||L[i].x1>MaxX+0.005)
continue;
if(L[i].x2<MinX || L[i].x1>MaxX)
return false;
tL=L[i];
if(tL.x1<MinX)
tL.x1=MinX;
if(tL.x2<MaxX)
tL.x2=MaxX;
if(!findL(tL))
return false;
}
}
}
return true;
}
void work()
{
int k;
if(m==1)
{
scale=0.005/(S[0].x2-S[0].x1+S[0].y2-S[0].y1);
ok=scale<=1 && check();
}
else for(k=0;k<n;k++)
if((L[k].x1-L[k].x2)*(S[1].x1-S[1].x2) || (L[k].y1-L[k].y2)*(S[1].y1-S[1].y2))
{
if(S[1].x1!=S[1].x2)
{
if(same(S[1].y1,pS.y))
{
if(!same(S[1].x1,pS.x))
scale=(L[k].x1-pL.x)/(S[1].x1-pS.x);
else
scale=(pL.x-L[k].x2)/(pS.x-S[1].x2);
}
else
scale=(L[k].y1-pL.y)/(S[1].y1-pS.y);
}
else
{
if(same(S[1].x1,pS.x))
{
if(!same(S[1].y1,pS.y))
scale=(L[k].y1-pL.y)/(S[1].y1-pS.y);
else
scale=(pL.y-L[k].y2)/(pS.y-S[1].y2);
}
else
scale=(L[k].x1-pL.x)/(S[1].x1-pS.x);
}
ok=scale<=1&&scale>delta&&check();
if(ok)
return ;
}
}
int main()
{
T=0;
while(scanf("%d %d",&m,&n) && (m||n))
{
for(i=0;i<m;i++)
S[i]=in();
for(i=0;i<n;i++)
L[i]=in();
ok=false;
for(i=0;i<n;i++)
for(j=0;j<m;j++) if(!ok)
{
tL=S[0];
S[0]=S[j];
S[j]=tL;
pL.x=L[i].x1;
pL.y=L[i].y1;
pS.x=S[0].x1;
pS.y=S[0].y1;
work();
if(ok)
break;
pL.x=L[i].x2;
pL.y=L[i].y2;
pS.x=S[0].x2;
pS.y=S[0].y2;
work();
if(ok)
break;
}
if(ok)
printf("Case %d: valid puzzle\n\n",++T);
else
printf("Case %d: impossible\n\n",++T);
}
return 0;
}