平面内两条线段的位置关系(相交)判定与交点求解 – Devymex

主意

立体内两条段落席位相干的论断在很多置于球面内部都迷住普遍的家用电器,比如,游玩、CAD、图形处置等。,两垂线交点的求解是AL的要紧组成使成比例。。在本提供免费入场券,本人将用盛行的报告来形容主流和。

同位关系,亦称为叉积,它是带菌者代数(解析几何学)的主意。。两维带菌者V1(x1, y1V2(x2, y2表面作品V1×v2=x1y2-y1x2。免得V1到v2是右旋地转动,表面作品是负的,相反,它是迅速的的。,在流行打中0,两个方针的确定是相同的的(划一)。。另外,本文议论了行事例和方程的主意。,请参阅线形的代数的有关主题。。

为了便于计算,同等级的的下定义如次::X同等级的越大,同等级的越大。,x同等级的相当,y同等级的较大。,x相等的总计y。。段落的较小端是0。,更大的完毕执意完毕。。

成绩

事先调整两条段落的起点站同等级的,求其席位相干,找出穿插点(免得在)。

辨析

两条段落的席位相干大抵可以分为三类:堆叠使成比例、没堆叠使成比例,但有穿插点。、无交点。戒除严守标准的成绩,率先,本人需求制服极度的堆叠的境遇。。

并存可分为:完整适合、一面之词堆叠、三使成比例堆叠。显然,两条段落的起止点都相同的即为完整适合;不料0相同的或不料起点相同的的为一面之词堆叠(睬:同等级的较小的又段落的起点与同等级的较大的又段落的0相同的时应论断为切成)。确定无论产生使成比例堆叠。,本人麝香率先判别无论划一。。设置段落L1(p1->p2和L2(p3->p4),在内地,P1(x)1, y1第第一段落的0。,p2(x2, y2第党派段的最后的事物。,p3(x3, y3第助手段落的0。,p4(x4, y4第助手的最后的事物。,可以认可两个带菌者。:

  • v1(x2-x1, y2-y1),v2(x4-x3, y4-y3)

若v1与v2表面作品V1×v2为0,则两条段落划一,可能性在使成比例堆叠。。继判别这两条划一线无论共线。,该方式是运用L1的一面之词和L2的一面之词排队矢径V。s与V2作同位关系,免得Vs与v2平行的地,这两个段落是共线的(三点共线)。。在共线形的的假设下,免得接收点小,则段落的末期的大于T。,使成比例并存。

没堆叠,要论断两条线无论切成,首要算法依赖于表面作品。。可是,表面作品的计算本钱对立较大。,免得有更多无内聚力的境遇,凌厉的回绝化验可以先做。:将两条段落处理两个矩形的斜列,并认可这两个矩形。。免得两个矩形不堆叠(x同等级的断绝关系或y同等级的)。

继举行尝试化验。。这两条切成的线麝香互切成叉。,简略地说,它是P。1和p2两点定居L..2两边和p3和p4两点定居L..1的安博,因而本人可以运用作品来做出判别。。辨别认可矢径S1(p3, p1), s2(p3, p2),免得是1×v2与s2×v2不一样总计(s)1->v2与s2->v2相反的旋转方针的确定,它解说了P1和p2定居L2的安博。移情可以判别3和p4无论以手围绕测量类似测量L1。免得上述的4穿插产品打中无论什么第一相等的总计0,这中间段落的起点在另又线上。。

当论断两条段落切成后,你可以处理穿插点。。自然,立体几何方式可以用来求交点。,列点斜方程填写。可是这会使处置特别境遇的斜率适合纠葛。,在运转中会呈现多个分区。,很难说证严守标准的。。本文采取矢径法。。

将交点设置为(x)0, y0),麝香使成为跟随方程。:

  1. x0-x1=k1(x2-x1)
  2. y0-y1=k1(y2-y1)
  3. x0-x3=k2(x4-x3)
  4. y0-y3=k2(y4-y3)

在内地,K1和k2是0的常数,免得是0。,这象征有堆叠的起点站。,这种境遇已被制服。。1路2路接线,3和4同时,使无效K1和k2可获:

  1. x0(y2-y1)-x1(y2-y1)=y0(x2-x1)-y1(x2-x1)
  2. x0(y4-y3)-x3(y4-y3)=y0(x4-x3)-y3(x4-x3)

将包括未知x0和y0将进行控告向左搬迁。,常数项向右的搬迁。,得:

  1. (y2-y1)x0+(x1-x2)y0=(y2-y1)x1+(x1-x2)y1
  2. (y4-y3)x0+(x3-x4)y0=(y4-y3)x3+(x3-x4)y3

两个常数项是1和b2

  • b1=(y2-y1)x1+(x1-x2)y1
  • b2=(y4-y3)x3+(x3-x4)y3

系数限定性的是D,用b1和b2掉换X0的系数所得系数限定性的是D1,掉换Y0的系数所得系数限定性的是D2,则有:

  • |D|=(x2-x1)(y4-y3)-(x4-x3)(y2-y1)
  • |D1|=b2(x2-x1)-b1(x4-x3)
  • |D2|=b2(y2-y1)-b1(y4-y3)

到这程度,可力图交点同等级的。。:

解毕。

C++/STL赚得

#include 
#include 
using namespace std;
struct POINTF {漂 x; float y;};
bool 平稳的(漂) f1, float F2) {
	return (ABS)(F1) - F2) < 1e-4f);
}
//判别两点无论相当
bool operator==(康斯特 POINTF &p1, const POINTF P2) {
	return (等), ) && Equal(P1).y, p2.y));
}
//比拟两点同等级的大小,先比拟x同等级的,若相同的则比拟y同等级的
bool operator>(康斯特 POINTF &p1, const POINTF P2) {
	return ( >  || (等), ) && p1.y > p2.y));
}
两带菌者积的计算
float operator^(康斯特 POINTF &p1, const POINTF P2) {
	return ( * p2.y - p1.y * );
}
确定两段传球的席位相干,找出穿插点(免得在)。恢复原来信仰的人值如次所示。:
[这是第一并存] 完整适合(6),1个起点站堆叠且共线(5)。,使成比例堆叠(4)
[没并存] 两端交点(3),手抄(2),成直角的(1),无十字架(0),限制因素误审(- 1)
int Intersection(POINTF p1, POINTF p2, POINTF p3, POINTF p4, POINTF Int) {
确保限制因素P1!=p2,p3!=p4
	if (P1) == p2 || p3 == P4) {
		return -1; 恢复原来信仰的人到1代表无论如何第一段落堆叠。,无法排队段落。
	}
便宜管理,确保每个区段的接收点提早。,完毕随后。
	if (P1) > P2) {
		swap(P1), P2);
	}
	if (P3) > P4) {
		swap(P3), P4);
	}
	//论断两段落无论完整适合
	if (P1) == p3 && p2 == P4) {
		return 6;
	}
找出两个段落的带菌者。
	POINTF v1 = { - , p2.y - p1.y}, v2 = {p4.x - p3.x, p4.y - p3.y};
求两个带菌者的同位关系,划一地,同位关系为0。
	float Corss = v1 ^ v2;
免得0划一
	if (P1) == P3) {
		Int = p1;
接收点堆叠,共线(划一)恢复原来信仰的人到5。;不划一于起点。,恢复原来信仰的人3
		return (等)Corss, 0) ? 5 : 3);
	}
免得完毕堆叠
	if (P2) == P4) {
		Int = p2;
起点站堆叠,共线(划一)恢复原来信仰的人到5。;不划一于起点。,恢复原来信仰的人3
		return (等)Corss, 0) ? 5 : 3);
	}
免得这两行完毕
	if (P1) == P4) {
		Int = p1;
		return 3;
	}
	if (P2) == P3) {
		Int = p2;
		return 3;
传球上述的判别,首尾点相重的境遇都被制服了
原因接收点同等级的对段落举行排序。免得段落1具有较大的接收点,被掉换者两条段落。
	if (P1) > P3) {
		swap(P1), P3);
		swap(P2), P4);
恢复原始计算带菌者及其同位关系
被掉换者(V1), v2);
		Corss = v1 ^ v2;
	}
处置两条划一线
	if (等)Corss, 0)) {
		//做带菌者v1(P1), p2Vs(P1),P3)的同位关系,确定无论共线
		POINTF vs = {p3.x - , p3.y - p1.y};
外作品是0线,两条划一线。,上面论断无论堆叠使成比例
		if (等)v1 ^ vs, 0)) {
前党派的接收点大于下党派的接收点。,这是并存。
			if (P2) > P3) {
				Int = p3;
				return 4; 恢复原来信仰的人值4表现段落的使成比例堆叠。
			}
免得三点缺点共线的,这两条划一线不尽然是共线的。。
不共线的共线传球没交集。
		return 0;
	} 以下竞争划一的境遇。,率先,凌厉的回绝化验。
X同等级的已被排序。,可直接地比拟。y同等级的麝香率先求两垂线的变憔悴和最低限度。
	float ymax1 = p1.y, ymin1 = p2.y, ymax2 = p3.y, ymin2 = p4.y;
	if (ymax1 < ymin1) {
		swap(ymax1, ymin1);
	}
	if (ymax2 < ymin2) {
		swap(ymax2, ymin2);
	}
	//免得以两段落为斜列的矩形不切成,则无交点
	if ( > p4.x ||  < p3.x || ymax1 < ymin2 || ymin1 > ymax2) {
		return 0;
穿插实验正在举行中。
	POINTF vs1 = { - p3.x, p1.y - p3.y}, vs2 = { - p3.x, p2.y - p3.y};
	POINTF vt1 = {p3.x - , p3.y - p1.y}, vt2 = {p4.x - , p4.y - p1.y};
	float s1v2, s2v2, t1v1, t2v1;
原因表面作品的算是,确定无论翻开它。
	if (等)s1v2 = vs1 ^ v2, 0) && p4 > p1 && p1 > P3) {
		Int = p1;
		return 2;
	}
	if (等)s2v2 = vs2 ^ v2, 0) && p4 > p2 && p2 > P3) {
		Int = p2;
		return 2;
	}
	if (等)t1v1 = vt1 ^ v1, 0) && p2 > p3 && p3 > P1) {
		Int = p3;
		return 2;
	}
	if (等)t2v1 = vt2 ^ v1, 0) && p2 > p4 && p4 > P1) {
		Int = p4;
		return 2;
	} //未交于线上,确定无论切成。
	if(s1v2 * s2v2 > 0 || t1v1 * t2v1 > 0) {
		return 0;
	} 上面是穿插横断的境遇。,该算法在文档中仔细阐明。
计算二阶限定性的的两个常数。
	float ConA =  * v1.y - p1.y * v1.x;
	float ConB = p3.x *  - p3.y * ;
计算限定性的D1和D2的值,系数限定性的除法,求交点同等级的。
	Int.x = (ConB * v1.x - ConA * ) / Corss;
	Int.y = (ConB * v1.y - ConA * ) / Corss;
成直角的恢复原来信仰的人1
	return 1;
}
//主重大聚会
int 主(空) {
随机尝试100个化验数据
	for (int) i = 0; i < 100; ++i) {
		POINTF p1, p2, p3, p4, Int;
		 = (float)(rand() % 10); p1.y = (float)(rand() % 10);
		 = (float)(rand() % 10); p2.y = (float)(rand() % 10);
		p3.x = (float)(rand() % 10); p3.y = (float)(rand() % 10);
		p4.x = (float)(rand() % 10); p4.y = (float)(rand() % 10);
		int nr = Intersection(P1), p2, p3, p4, Int);
		cout << "[(";
		cout << (int)) << '','' << (int))p1.y << "),(";
		cout << (int)) << '','' << (int))p2.y << ")]--[(";
		cout << (int))p3.x << '','' << (int))p3.y << "),(";
		cout << (int))p4.x << '','' << (int))p4.y << ")]: ";
		cout << nr;
		if (nr > 0) {
			cout << ''('' << Int.x << '','' << Int.y << '')'';
		}
		cout << endl;
	}
	return 0;
}