GDI+에서 두 줄의 교차점을 어떻게 결정합니까?
문제
Visio와 비슷한 드로잉 표면이있는 응용 프로그램을 만들기 위해 .NET을 사용하고 있습니다. UI는 화면의 두 객체를 Graphics.Drawline으로 연결합니다. 이 간단한 구현은 잘 작동하지만 표면이 더 복잡해지면 객체를 표현할 수있는보다 강력한 방법이 필요합니다. 이러한 강력한 요구 사항 중 하나는 두 줄의 교차점을 결정하는 것이므로 어떤 종류의 그래픽을 통해 분리를 표시 할 수 있습니다.
그래서 내 질문은 누구든지 이것을 할 방법을 제안 할 수 있습니까? 어쩌면 다른 기술 (그래프 비즈) 또는 알고리즘이 있습니까?
해결책
y = mx + c에 의한 라인의 표현은 컴퓨터 그래픽에 문제가 있습니다. 수직선은 m이 무한해야하기 때문입니다.
또한 컴퓨터 그래픽의 라인은 수학 라인과 달리 시작 및 엔드 포인트가 있습니다. 하나는 교차점이 해당 라인 세그먼트에있는 경우 일반적으로 선의 교차에만 관심이 있습니다.
벡터 x1에서 x1+v1까지, 하나는 벡터 x2에서 x2+v2의 라인 세그먼트가있는 경우 다음을 정의합니다.
a = (v2.v2 v1.(x2-x1) - v1.v2 v2.(x2-x1)) / ((v1.v1)(v2.v2) - (v1.v2)^2)
b = (v1.v2 v1.(x2-x1) - v1.v1 v2.(x2-x1)) / ((v1.v1)(v2.v2) - (v1.v2)^2)
벡터 p = (px, py), q = (qx, qy)의 경우, pq는 도트 제품 (px * qx + py * qy)입니다. 먼저 (v1.v1) (v2.v2) = (v1.v2)^2를 확인하십시오 - 그렇다면 선이 평행하고 교차하지 않습니다.
평행하지 않으면 0 <= a <= 1 및 0 <= b <= 1이면 교차점은 두 줄 세그먼트에 있고 지점에 의해 주어집니다.
x1 + a * v1
편집하다 A와 B에 대한 방정식의 도출은 다음과 같습니다. 교차점은 벡터 방정식을 만족시킵니다
x1 + a*v1 = x2 + b*v2
이 방정식의 도트 곱을 사용하여 v1
, 그리고 함께 v2
, 우리는 두 가지 방정식을 얻습니다.
v1.v1*a - v2.v1*b = v1.(x2-x1)
v1.v2*a - v2.v2*b = v2.(x2-x1)
a와 b에 대한 두 개의 선형 방정식을 형성합니다. 이 시스템을 해결하는 데 (첫 번째 방정식에 v2.v2를 곱한 것과 두 번째 방정식을 v1.v1을 곱하고, 빼기 또는) a와 b에 대한 방정식을 제공합니다.
다른 팁
참조 프레임을 첫 번째 줄 세그먼트와 정렬하기 위해 참조 프레임을 회전 시키면 (원점이 첫 번째 줄의 시작이되고, 첫 번째 줄의 벡터가 x 축을 따라 확장 됨) 질문이 어디에 있습니까? 두 번째 줄은 어디에 있습니까? 새로운 좌표계에서 X 축을 누르십시오. 이것은 대답하기가 훨씬 쉬운 질문입니다. 첫 번째 줄이 호출되는 경우 A
그리고 그것은에 의해 정의됩니다 A.O
라인의 원점과 'av'는 라인의 벡터이므로 A.O + A.V
선의 끝점입니다. 기준 프레임은 행렬에 의해 정의 될 수 있습니다.
| A.V.X A.V.Y A.O.X |
M = | A.V.Y -A.V.X A.O.Y |
| 0 0 1 |
균질 한 좌표 에서이 매트릭스는 선을 매핑하는 기준 프레임의 기초를 제공합니다. A
x 축에서 0 ~ 1입니다. 이제 변환 된 선을 정의 할 수 있습니다 B
처럼:
C.O = M*(B.O)
C.V = M*(B.O + B.V) - C.O
어디에 *
균질 한 좌표에 대해 연산자가 올바르게 정의되었습니다 (이 경우 3 개의 공간에서 2 공간으로의 투영). 이제 남아있는 모든 것은 어디에 있는지 확인하고 보는 것입니다. C
해결과 동일한 x 축을칩니다 Y
파라 메트릭 방정식의 측면 C
~을 위한 t
:
C.O.Y + t * C.V.Y = 0
-C.O.Y
t = --------
C.V.Y
만약에 t
그렇다면 0 ~ 1 범위에 있습니다 C
라인 세그먼트 내부의 x 축을칩니다. x 축에 착륙하는 장소는 매개 변수 방정식의 x 측면에 의해 주어집니다. C
:
x = C.O.X + t * C.V.X
만약에 x
0 ~ 1 범위에 있으면 교차로가 A
라인 세그먼트. 그런 다음 원래 좌표 시스템에서 다음과 같이 포인트를 찾을 수 있습니다.
p = A.O + A.V * x
물론 어느 라인 세그먼트가 0 길이인지 확인하려면 먼저 확인해야합니다. 또한 C.V.Y = 0
평행선 세그먼트가 있습니다. 만약에 C.V.X
또한 Colinear 라인 세그먼트가있는 0입니다.