분류

2017년 3월 21일 화요일

JAVASCRIPT 두 직선의 교차점을 찾는 법

자바스크립트를 통해 GUI를 구성해보기 위해 이런저런 실험을 하는 중인데, 여러 도형간을 연결하는 선을 만들고 싶었고, 해당 선을 만들려다 보니, 각 선분이 교차하는 지점이 매번 도형 내부에 위치되어 보기 싫어지는 현상이 발생했다.

각 도형의 외곽선과, 내부 선의 교차점을 찾아내 첫 도형의 교차점에서 시작해 다음 도형의 교차점에서 종료되는 코드를 만들고 싶었고, 해당 교차점을 찾아내는 것이 의외로 수학의 기하학이라는 수학을 활용해야 하는 복잡한 연산임을 깨닫고, 이런 저런 검색을 하게되었다.

두 직선의 교차점을 찾는 방법을 프로그래밍 코드화 하기 위해 제타위키 에서 나온 교차점 공식을 적용 한 코드를 작성하게 되었다.

두 직선의 교차점 - 제타위키

도형에는 외곽선이 하나가 아닌 여러개이기에,
해당 선분을 빼내어 배열에 넣고 해당 배열의 각 변의 시작점과 종로점의 x축, y축을
각각 (x1, y1, x2, y2)로 입력하였다.

또한 교차를 검사할 대상의 경우 단 하나의 선이므로, 해당 선의 좌표는 x1, y1, x2, y2로 이루어진 하나의 선이다.

/**
 * 기하학 공식 대입 도형의 외곽선과 라인의 크로스포인트를 찾는 역할
 * @param ob1 크로스 포인트를 찾을 도형의 선 집합
 * @param ob2 크로스포인트를 찾을 선
 * @returns
 */

  1. function findCrossPoint(sr, tr){
  2. var pos = [];
  3. for(var i = 0; i < sr.length; i++){
  4. var tmp = sr[i]; 
  5. var p1 = (tmp.x1 - tmp.x2)*(tr.y1 - tr.y2) - (tmp.y1-tmp.y2)*(tr.x1-tr.x2);//분모로 사용됨
  6. // p1 ==0 이면 평행선 또는 일치 이므로 제외(분모)
  7. if(p1 != 0){
  8. var x = 0; 
  9. var y = 0; 
  10. var x = (((tmp.x1 * tmp.y2) - (tmp.y1 * tmp.x2))*(tr.x1 - tr.x2) 
  11. - (tmp.x1 - tmp.x2) * ((tr.x1 * tr.y2) - (tr.y1 * tr.x2))) / p1; 
  12. var y = (((tmp.x1 * tmp.y2) - (tmp.y1 * tmp.x2))*(tr.y1 - tr.y2) 
  13. - (tmp.y1 - tmp.y2)*((tr.x1 * tr.y2) - (tr.y1 * tr.x2))) / p1; 
  14. if((x - tmp.x1) * (x - tmp.x2) <= 0 && (y - tmp.y1) * (y - tmp.y2) <= 0 //교점이 1선분 위에 있고
  15.    && (x - tr.x1) * (x - tr.x2) <= 0 && (y - tr.y1) * (y - tr.y2) <= 0 //교점이 2선분 위에 있을경우
  16. ){
  17. pos.push({ x : x , y : y }) ; 
  18. }
  19. }
  20. }
  21. return pos; 
  22. }

위에서 if문을 통해서 선분 교점의 위치가 음수나 0보다 작거나 같다는 검증을 하는 이유는 선의 전체 거리가 아닌 확장되는 축의 방향을 기준으로 교점을 검사하기에 경우에 따라서 선분이 더 확장될경우 생성되는 교점마저 추출되기 때문이다.


또한 배열에 좌표값을 넣어서 반환하는 이유는, 하나의 선이 두개 이상의 도형 선을 교차하여 통과하는 일이 발생할 수 있기 때문이다. 선하나 제대로 긋겠다고 기하학을 사용하게 될줄은... ㅎㅎ; 고딩떄 수학을 안한것이 새삼 후회하게 된다.

댓글 없음:

댓글 쓰기