특정 pnt
에서
두 점 segment_s
(s), segment_e
(e)로 정의된 line segment를 포함하는 line으로
수선의 발(foot of perpendicular line)를 내리는 경우는 다음과 같음.
위 그림에서 x
가 바로 foot of perpendicular line임.
다음은 foot of perpendicular line (intersection
)과 line-segment 중에서 pnt
와 가장 가까운 점 (closet_pnt
)을 반환하는 function을 구현한 예제임.
def find_intersection_pnt( segment_s, segment_e, pnt):
# Calculate the direction vector of the line segment defined by segment_s and segment_e
line_segment_vector = (segment_e[0] - segment_s[0],
segment_e[1] - segment_s[1])
# Calculate the direction vector of the perpendicular line
perpendicular_vector = (-line_segment_vector[1],
line_segment_vector[0])
# Calculate the closest point on the line segment to the foot of the perpendicular line
# \text{proj}_\textbf{w}\textbf{x}=\dfrac{\bf{x}\cdot\bf{w}}{\|\bf{w}\|^2}\bf{w}
projection = (pnt[0] - segment_s[0], pnt[1] - segment_s[1]) # set segment_s to origin
dot_product = projection[0] * line_segment_vector[0] + projection[1] * line_segment_vector[1]
projection_length = dot_product / (line_segment_vector[0] ** 2 + line_segment_vector[1] ** 2)
intersection_pnt = (segment_s[0] + line_segment_vector[0] * projection_length,
segment_s[1] + line_segment_vector[1] * projection_length)
# Check if the intersection_point lies on the line segment
is_on_segment = (segment_s[0] <= intersection_pnt[0] <= segment_e[0] or
segment_s[0] >= intersection_pnt[0] >= segment_e[0]) and \
(segment_s[1] <= intersection_pnt[1] <= segment_e[1] or
segment_s[1] >= intersection_pnt[1] >= segment_e[1])
# Calculate the closest point
if is_on_segment:
closest_pnt = intersection_pnt
else:
# Choose the closest point between the foot of the perpendicular line and the endpoints of the segment
dist_start = (intersection_pnt[0] - segment_s[0]) ** 2 + (intersection_pnt[1] - segment_s[1]) ** 2
dist_end = (intersection_pnt[0] - segment_e[0]) ** 2 + (intersection_pnt[1] - segment_e[1]) ** 2
if dist_start < dist_end:
closest_pnt = segment_s
else:
closest_pnt = segment_e
return intersection_pnt,closest_pnt
# Test
segment_s = (0, 0)
segment_e = (4, 2)
pnt = (5, 5)
intersection,closet_pnt = find_intersection_pnt(segment_s, segment_e, pnt)
print(f"Intersection point: {intersection}")
print(f"closet point: {closet_pnt}")
계산 효율보다는, 가독성에 초점을 맞춘 코드이며 linear algebra에서 orthogonal projection (정사영)을 이용하여 구현함.
https://dsaint31.tistory.com/entry/Math-Orthogonal-Projection-%EC%A0%95%EC%82%AC%EC%98%81
line-segment의 시작점을 origin으로 처리하여 구함.
foot of perpendicular는 특정 point가 선에서 어디에 있느냐에 따라 distance의 +,-를 정해지는 경우에 보통 구해지고, 단순히 거리만을 이용할 때는 좀더 단순하게 구할 수 있음. (몇가지 단계만 빠질 뿐 거의 똑같음)
위의 구현물과 그림을 그린 코드 gist는 다음과 같음.
https://gist.github.com/dsaint31x/7853330c85e783dba7825faaa7300d5b
'Python' 카테고리의 다른 글
[Python] dictionary (Mapping type) : basic (0) | 2023.07.11 |
---|---|
[Python] Dictionary's methods (0) | 2023.07.11 |
[Python] atan2 (1) | 2023.07.10 |
[Python] lambda expression and map, filter, reduce. (0) | 2023.07.07 |
[Python] os 모듈의 함수들 : file과 directory 관련 (0) | 2023.07.04 |