/*
向量a ,向量b
c=a-b c的方向指向的是a 指向的是被减数
*/
#include<bits/stdc++.h>
#define eps (1e-10)
using namespace std;
class Point
{
public:
double x,y;
Point(double _x=0,double _y=0):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);}
double norm(){return x*x+y*y;}
double ABS(){return sqrt(norm());} //俩点间的距离
};
struct Segment
{
Point p1,p2;
Segment(){}
Segment(Point _p1,Point _p2):p1(_p1),p2(_p2){}
};
double dot(Point a,Point b)//求内积 就是向量a*b
{
return a.x*b.x+a.y*b.y;
}
//外积的值为a与b向量构成的平行四边形面积的值
double cross(Point a,Point b)//求外积
{
return a.x*b.y-a.y*b.x;
}
//判断是否正交 向量内积:a*b=|a||b|*cos(Y) 当cos为0时正交(90,-90垂直)
//a*b=a.x*b.x+a.y*b.y;
bool solve1(Point a,Point b)//是否正交
{
double f=a.x*b.x+a.y*b.y;
if(fabs(f-0.0)<eps) return true;
else return false;
}
//判断是否平行 向量外积:|a*b|=|a||b|sin(Y) 当sin为0时平行(180,0平行)
//|a*b|=|a|*|b|*sin(Y)
bool solve2(Point a,Point b)//是否平行
{
double f=a.x*b.y-a.y*b.x;
if(fabs(f-0.0)<eps) return true;
else return false;
}
/*
求垂足x:对于给定的三点p1,p2,p从点p向通过p1,p2的直线引一条垂线
base=p2-p1;
hypo=p-p1;
x=s.p1+base*(hypo*base/|base|^2); hypo*base 可以用向量内积求
*/
Point solve3(Segment s,Point p)//求投影点
{
Point base=s.p2-s.p1;
double r=dot(p-s.p1,base)/base.norm();
return s.p1+base*r;
}
/*
求投影点x:对于给定的三点p1,p2,p从点p向通过p1,p2的直线为对称轴与点p
成线对称点为x
通过求solve3的垂足延长一倍就可以求x
*/
Point solve4(Segment s,Point p)//求映象
{
return p+(solve3(s,p)-p)*2.0;
}
/*
Point a=p1-p0;
Point b=p2-p0;
1.外积大小cross(a,b)为正时,可确定b在a的逆时针方向
sin(Y)(Y在0-180)所以是正数
2. 外积大小cross(a,b)为负时,可确定b在a的顺时针方向
3.(1,2)不符合 表示p2在直线p0p1上(注意是直线),cos(Y)大于90或小于-90
度时为负,因此a与b的内积dot(a,b)负时,可确定p2位于线段p0p1后方
即p2->p0->p1
4.不是3时,有俩种p0->p1-p2或者p0->p2->p1如果b的大小大于a的大小,即为
p0->p1->p2;
5.不符合4,可以确定p2位于线段p0p1上
*/
int ccw(Point p0,Point p1,Point p2)//判断三个点相对位置
{
Point a=p1-p0;
Point b=p2-p0;
if(cross(a,b)>eps) return 1;//p0,p1,p2成逆时针方向
if(cross(a,b)<-eps) return -1;//p0,p1,p2成顺时针方向
if(dot(a,b)<-eps) return 2;//p2 p0 p1一次排列在同一直线上
if(a.norm()<b.norm()) return -2;// p0 p1 p2一次排列在同一直线上
return 0;//p2在线段p0p1上
}
bool intersect(Point p1,Point p2,Point p3,Point p4)//判断线段是否相交 通过ccw来判断
{
return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0&&ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}
/*
点a与点b之间的距离等于向量a-b或b-a的绝对值。
*/
double getdis(Point a,Point b)//求俩点间的距离
{
return (a-b).ABS();
}
/*
设直线p1 p2上的向量为a=p2-p1,p与p1构成的向量b=p-p1
则点p与直线p1p2的距离d就等于a,b构成的平行四边形的高
用a与b外积的大小(平行四边形的面积)除以a的大小|a|即可求出高d
d=|a*b|/|a|=|(p2-p1)*(p-p1)|/|p2-p1|;
*/
//注意:这里Segmet s是不规范的应该是 Line s 才对
double getdis_Li(Segment s,Point p)//点与直线的距离
{
return abs(cross(s.p2-s.p1,p-s.p1)/(s.p2-s.p1).ABS());
}
double getdis_sp(Segment s,Point p)//点与线段的距离
{
if(dot(s.p2-s.p1,p-s.p1)<0.0) return (p-s.p1).ABS();
if(dot(s.p1-s.p2,p-s.p2)<0.0) return (p-s.p2).ABS();
return getdis_Li(s,p);
}
double getdis_ss(Segment s1,Segment s2)//线段与线段之间的距离
{
if(intersect(s1.p1,s1.p2,s2.p1,s2.p2)) return 0.0;
return min(min(getdis_sp(s1,s2.p1),getdis_sp(s1,s2.p2)),min(getdis_sp(s2,s1.p1),getdis_sp(s2,s1.p2)));
}
/*
t:线段s1的长度与点s1.p1到交点的x的距离之比为t
d1:s1 和s2.p1构成的平行四边形的高
d2:同理
则:d1:d2=t:(t-1)
x=s1.p1+(s1.p2-s1.p1)*t;
*/
Point get_s1s2_point(Segment s1,Segment s2)//在s1和s2有交点的情况下,求s1和s2的交点
{
Point base=s2.p2-s2.p1;
double d1=abs(cross(base,s1.p1-s2.p1));
double d2=abs(cross(base,s1.p2-s2.p1));
double t=d1/(d1+d2);
return s1.p1+(s1.p2-s1.p1)*t;
}
int main()
{
int T;scanf("%d",&T);
while(T--){
double x0,y0,x1,y1,x2,y2,x3,y3;
scanf("%lf %lf %lf %lf %lf %lf %lf %lf",&x0,&y0,&x1,&y1,&x2,&y2,&x3,&y3);
Point p0(x0,y0),p1(x1,y1),p2(x2,y2),p3(x3,y3);
Segment s1(p0,p1),s2(p2,p3);
printf("%.10f %.10f\n",get_s1s2_point(s1,s2).x,get_s1s2_point(s1,s2).y);
}
return 0;
}