예제 #1
0
def calc_seg_intersect(xa, ya, xb, yb, xc, yc, xd, yd):

	s_abc = cross(xb - xa, yb - ya, xc - xa, yc - ya)
	c_abc = dblcmp(s_abc)
	c_cda = dblcmp(cross(xd - xc, yd - yc, xa - xc, ya - yc))
	
	if c_abc == 0:
		f = between(xc, yc, xa, ya, xb, yb)
		if f is not None:
			return xc, yc, f, 0.0, (c_cda == 1), False

	if c_cda == 0:
		f = between(xa, ya, xc, yc, xd, yd)
		if f is not None:
			return xa, ya, 0.0, f, False, (c_abc == 1)
		
	s_abd = cross(xb - xa, yb - ya, xd - xa, yd - ya)
	c_abd = dblcmp(s_abd)
	
	c_cdb = dblcmp(cross(xd - xc, yd - yc, xb - xc, yb - yc))

	if c_abd * c_abc < 0 and c_cda * c_cdb < 0:
		i = 1.0 * s_abc / (s_abc - s_abd)
		j = 1.0 - i
		res_x = xc * j + xd * i
		res_y = yc * j + yd * i
		return res_x, res_y, between(res_x, res_y, xa, ya, xb, yb), i, (c_cda == 1), (c_abc == 1)
	return None, None, None, None, (c_cda == 1), (c_abc == 1)
예제 #2
0
def get_seg_proper_intersect(xa, ya, xb, yb, xc, yc, xd, yd):
	s_abd = cross(xb - xa, yb - ya, xd - xa, yd - ya)
	c_abd = dblcmp(s_abd)
	s_abc = cross(xb - xa, yb - ya, xc - xa, yc - ya)
	c_abc = dblcmp(s_abc)
	c_cda = dblcmp(cross(xd - xc, yd - yc, xa - xc, ya - yc))
	c_cdb = dblcmp(cross(xd - xc, yd - yc, xb - xc, yb - yc))
	if c_abd * c_abc >= 0 or c_cda * c_cdb >= 0:
		return None
	i = 1.0 * s_abd / (s_abd - s_abc)
	j = 1.0 - i
	return xd * i + xc * j, yd * i + yc * j
예제 #3
0
def is_seg_intersect(xa, ya, xb, yb, xc, yc, xd, yd):
	c_abd = dblcmp(cross(xb - xa, yb - ya, xd - xa, yd - ya))
	if c_abd == 0 and between(xd, yd, xa, ya, xb, yb) <= 0:
		return True
	c_abc = dblcmp(cross(xb - xa, yb - ya, xc - xa, yc - ya))
	if c_abc == 0 and between(xc, yc, xa, ya, xb, yb) <= 0:
		return True
	c_cda = dblcmp(cross(xd - xc, yd - yc, xa - xc, ya - yc))
	if c_cda == 0 and between(xa, ya, xc, yc, xd, yd) <= 0:
		return True
	c_cdb = dblcmp(cross(xd - xc, yd - yc, xb - xc, yb - yc))
	if c_cdb == 0 and between(xb, yb, xc, yc, xd, yd) <= 0:
		return True
	return c_abd * c_abc < 0 and c_cda * c_cdb < 0
예제 #4
0
def between(xc, yc, xa, ya, xb, yb):
	if math.fabs(xb - xa) > math.fabs(yb - ya):
		da = xa - xc
		db = xb - xc
	else:
		da = ya - yc
		db = yb - yc
	sa = dblcmp(da)
	if sa == 0:
		return 0.0
	sb = dblcmp(db)
	if sb == 0:
		return None
	if sa * sb < 0:
		return 1.0 * da / (da - db)
	return None
예제 #5
0
def get_seg_intersect(xa, ya, xb, yb, xc, yc, xd, yd):
	res = []
	s_abd = cross(xb - xa, yb - ya, xd - xa, yd - ya)
	c_abd = dblcmp(s_abd)
	if c_abd == 0 and between(xd, yd, xa, ya, xb, yb) <= 0:
		res.append((xd, yd))
	s_abc = cross(xb - xa, yb - ya, xc - xa, yc - ya)
	c_abc = dblcmp(s_abc)
	if c_abc == 0 and between(xc, yc, xa, ya, xb, yb) <= 0:
		res.append((xc, yc))
	c_cda = dblcmp(cross(xd - xc, yd - yc, xa - xc, ya - yc))
	if c_cda == 0 and between(xa, ya, xc, yc, xd, yd) < 0:
		res.append((xa, ya))
	c_cdb = dblcmp(cross(xd - xc, yd - yc, xb - xc, yb - yc))
	if c_cdb == 0 and between(xb, yb, xc, yc, xd, yd) < 0:
		res.append((xb, yb))
	# 如果至少有一个点与另一条线段共线,那么此时可以断定交点已经全部求完
	if len(res) > 0:
		return res
	if c_abd * c_abc < 0 and c_cda * c_cdb < 0:
		i = 1.0 * s_abd / (s_abd - s_abc)
		j = 1.0 - i
		res.append((xd * i + xc * j, yd * i + yc * j))
	return res
예제 #6
0
def is_seg_proper_intersect(xa, ya, xb, yb, xc, yc, xd, yd):
	c_abd = dblcmp(cross(xb - xa, yb - ya, xd - xa, yd - ya))
	c_abc = dblcmp(cross(xb - xa, yb - ya, xc - xa, yc - ya))
	c_cda = dblcmp(cross(xd - xc, yd - yc, xa - xc, ya - yc))
	c_cdb = dblcmp(cross(xd - xc, yd - yc, xb - xc, yb - yc))
	return c_abd * c_abc < 0 and c_cda * c_cdb < 0
예제 #7
0
def between(xc, yc, xa, ya, xb, yb):
	if math.fabs(xb - xa) > math.fabs(yb - ya):
		return dblcmp(xa - xc) * dblcmp(xb - xc)
	else:
		return dblcmp(ya - yc) * dblcmp(yb - yc)
예제 #8
0
def decal_2d(rect, tri):
	p0, p1, p2, p3 = rect
	pa, pb, pc = tri
	
	cw = dblcmp(cross(pb[0] - pa[0], pb[1] - pa[1], pc[0] - pb[0], pc[1] - pb[1]))
	if cw == 0:	# 三角形面积为0
		return ()
	if cw < 0:
		pb, pc = pc, pb
		tri = (pa, pb, pc)

	rect_e = ((p0, p1), (p1, p2), (p2, p3), (p3, p0))
	tri_e = ((pa, pb), (pb, pc), (pc, pa))
	
	rect_p_seq = ([], [], [], [])
	tri_p_seq = ([], [], [])	
	rp_inside = [True] * 4
	pid = 0
	for j, te in enumerate(tri_e):
		tp_inside = True	# 三角形的顶点是否在矩形的内部
		for i, re in enumerate(rect_e):
			x, y, f1, f2, tp_on_left, rp_on_left = calc_seg_intersect(
				te[0][0], te[0][1], te[1][0], te[1][1],
				re[0][0], re[0][1], re[1][0], re[1][1],)
			if x is not None:
				tri_p_seq[j].append((f1, (x, y), pid, i))
				rect_p_seq[i].append((f2, (x, y), pid, j))
				pid += 1
			if not tp_on_left:	# 只要有不在任意一条边的左侧,都out
				tp_inside = False
			if not rp_on_left:
				rp_inside[i] = False
		if tp_inside:
			tri_p_seq[j].append((0.0, tri[j], pid, None))
			pid += 1
	for i in range(4):
		if rp_inside[i]:
			rect_p_seq[i].append((0.0, rect[i], pid, None))
			pid += 1
	
	if pid < 3:
		return ()

	# 排序,并找一个点作为起始点	
	start_pid = None
	seq = None
	p_index = None
	for i, seg_p_seq in enumerate(tri_p_seq):
		seg_p_seq.sort()
		if start_pid is None and seg_p_seq:
			start_pid = seg_p_seq[0][2]
			seq = tri_p_seq
			p_index = (i, 0)
	for i, seg_p_seq in enumerate(rect_p_seq):
		seg_p_seq.sort()
		if start_pid is None and seg_p_seq:
			start_pid = seg_p_seq[0][2]
			seq = rect_p_seq
			p_index = (i, 0)		

	ret = []
	while True:
		i, j = p_index
		f, p, pid, rev_i = seq[i][j]
		ret.append(p)
		
		# 需要切换到另外一个序列上
		if rev_i is not None and j == len(seq[i]) - 1:
			next_p_seq = seq[(i + 1) % len(seq)]
			if not next_p_seq or dblcmp(next_p_seq[0][0]) != 0:
				if seq == tri_p_seq:
					seq = rect_p_seq
				else:
					seq = tri_p_seq
				for k, (_f, _p, _pid, _rev_i) in enumerate(seq[rev_i]):
					if pid == _pid:
						i, j = p_index = (rev_i, k)
						break
		# 找下一个顶点,此时可以允许换边
		j += 1
		if j < len(seq[i]):
			p_index = (i, j)
		else:
			i = i + 1
			if i >= len(seq):
				i = 0
			j = 0
			p_index = (i, j)
		try:
			pid = seq[i][j][2]
		except IndexError:
			print ("f*****g algorithm error")
			return ()
		if pid == start_pid:
			break
	return ret