선분 교차 3
난이도
Platinum 5
인증
문제
2차원 좌표 평면 위의 두 선분 L1, L2가 주어졌을 때, 두 선분이 교차하는지 아닌지 구해보자. 한 선분의 끝 점이 다른 선분이나 끝 점 위에 있는 것도 교차하는 것이다.
L1의 양 끝 점은 (x1, y1), (x2, y2), L2의 양 끝 점은 (x3, y3), (x4, y4)이다.
입력
첫째 줄에 L1의 양 끝 점 x1, y1, x2, y2가, 둘째 줄에 L2의 양 끝 점 x3, y3, x4, y4가 주어진다.
출력
L1과 L2가 교차하면 첫째 줄에 1, 아니면 0을 출력한다.
두 선분이 한 점에서 교차하는 경우 둘째 줄에 교차하는 점의 x좌표와 y좌표를 공백으로 구분해 출력한다. 한 점에서 교차하지 않는 경우에는 둘째 줄을 출력하지 않는다.
좌표의 절대/상대 오차는 10-9까지 허용한다.
예제 입력
1 1 5 5
1 5 5 1
예제 출력
1
3 3
해설 및 후기
1,2 에서 선분 교차에 대한 판정을 ccw를 이용해서 할 수 있었다. 이번에는 선분 교차점까지 구하는 것이 목표이다. 총 8개의 점을 알고 있을때, 선분의 교차점을 수식으로 쉽게 구할 수 있다. 여러 케이스의 처리가 중요한데, 특히 평행한 떨어진 선분을 처리하는 방법이나, 평행하지 않은 한 포인트로부터 연결된 선분을 찾아내고 교차점을 구하는 것이 어려웠다.
제출 코드
import sys
x1,y1,x2,y2 = map(int, sys.stdin.readline().rstrip().split())
x3,y3,x4,y4 = map(int, sys.stdin.readline().rstrip().split())
def ccw(a,b,c):
s = (b[0]-a[0])*(c[1]-a[1]) - (b[1]-a[1])*(c[0]-a[0])
if(s > 0): return 1
elif (s == 0): return 0
else: return -1
a = [x1, y1]
b = [x2, y2]
c = [x3, y3]
d = [x4, y4]
ab = (ccw(a,b,c) * ccw(a,b,d))
cd = (ccw(c,d,a) * ccw(c,d,b))
if((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) == 0):
if(ab == 0 and cd == 0):
min1 = min(a,b)
max1 = max(a,b)
min2 = min(c,d)
max2 = max(c,d)
if(min1 <= max2 and max1 >= min2):
print(1)
l = []
if(min2 == max1):
l.append(max1)
if(max2 == min1):
l.append(min1)
if(len(l)==1):
print(l[0][0], l[0][1])
else:
print(0)
else:
print(0)
elif(ab <= 0 and cd <= 0):
print(1)
try:
px = ((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4))
py = ((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4))
print(px,py)
except:
pass
else:
print(0)