기울기와 한점이 주어졌을 때 동일한 거리만큼 떨어진 두 점 구하기.
제목을 줄이려다가 보니 제목이 좀 모호한데요.. 다시 정리하자면
기울기가 M이고 임의의 점 P(PX, PY)가 주어질때 P와 일직선상에 있으면서 거리가 T인 점(두개겠죠?)을 구하는 코드
를 작성하려 합니다. 코드를 작성하기 앞서 10년도 더 전에 배웠던 점과 직선의 방정식등을 구글링(이런걸 구글링 하게 될 줄이야..-_-) 해서 공식과 의사 코드를 작성해 봤습니다.
1. 우선 기울기가 M이고 임의의 점 P(PX, PY)를 지나는 직선의 방정식
직선의 방정식을 y=ax + b 라고 하면,
PY = M * PX + b
b = PY - (M * PX)
∴ y = Mx + (PY - (M * PX)) ........ (가)
2. 이어서 점과 직선사이의 거리
어떤 점 N(x,y)와 P(PX, PY) 사이의 거리를 T라 하면
T = √(PX-x)² + (PY-y)²
T² = (PX-x)² + (PY-y)² ............(나)
3. N은 (가)의 직선에 속하는 점이다. 그래서 (나)식을 풀면
T² = PX² - 2PXx + x² + PY² - 2PYy + y² (대문자가 연이어 있는것은 곱셈이 아니라 하나의 상수입니다.)
(가)식의 y를 풀어진 (나)에 대입하면..
T² = PX² - 2PXx + x² + PY² - 2PY * (Mx + (PY - (M * PX))) + (Mx + (PY - (M * PX)))²
알아 보기 쉽게 상수를 정리해 보겠습니다.
a = T²
b = PX
c = PY
d = PY - (M * PX)
그러면
a² = b² - 2bx + x² + c² - 2c * (Mx + d) + (Mx + d)²
a² = b² - 2bx + x² + c² - 2cMx - 2cd + (Mx)² + 2dMx + d²
위 식에서 우변을 0으로 만들면..
(M²+1)x² + (2dM - 2b - 2cM)x + (b² + c² - 2cd + d² - a²) = 0
이렇게 해서 Ax² + Bx + C = 0 의 형태를 만들고,
근의 공식인
x = -B ± √B² - 4AC / 2A
에 넣어 x를 구하고 이 x를 (가)식에 넣어 y를 구한다.
이게 제가 생각한 방식입니다.
코드로 구현 할때는
M = 기울기 PX = 주어진 점의 X좌표 PY = 주어진 점의 Y좌표 T = 주어진 점으로 부터 떨어진 거리 A = (M*M) + 1; B = (2 * (PY - (M * PX)) * M) - (2 * PX) - (2 * PY * M); C = (PX * PX) + (PY * PY) - (2 * PY * (PY - (M * PX))) + ((PY - (M * PX)) * (PY - (M * PX))) - (T * T); D = (B * B) - 4 * (A * C); if D > 0 x1 = ((-1 * B) + sqrt(D)) / (2 * A); x2 = ((-1 * B) - sqrt(D)) / (2 * A); y1 = (M * x1) + (PY - (M * PX)); y2 = (M * x2) + (PY - (M * PX)); else if D == 0 // 전제한 조건으로 부터 근이 한개만 나올 수는 없음 return -1; else D < 0 return -1;
이렇게 되겠죠...
테스트 프로그램을 작성해서 몇 가지 넣어 본 결과 잘되는 것 같긴 합니다만...
이렇게 수학적 방법을 동원해서 알고리즘을 작성하는 방법 밖에는 없는 것인지..
다른 방법은 없는 것인지..
다른 방법은 없다면 제가 작성한 저 방법이 맞는 것인지..
혹시 심심한 분들..
제가 생각한것 보다 더 깔끔하고 뭔가 아티스틱한 알고리즘 없을 랑가요...
댓글
sin , cos 이 연산 cost
sin , cos 이 연산 cost 가 싸다면
기울기 가 이루는 각 X = inverse of tangent '기울기' 를 이용해 X 를 구하고, ( 단 기울기가 0 이거나 무한대가 아니어야겠죠. 0 인경우는 X 축 쪽으로만 더하거나 빼면 끝이므로 )
거리가 D 라고 한다면,
원래 점 P(px,py) 이고 구하는 점 P1 은 (px + D cos X , py + D sin X ) , P2 는 ( px - D cos X , py - D six X )
입니다.
일반적으로 sin , cos 는 cost 가 크므로 어느쪽이 빠른지는 잘 생각해보셔서 사용하세요. ( 하드웨어에 따라 다르겠죠~ )
Neogeo - Future is Now.
Neogeo - Future is Now.
...
dx = T / sqrt(1 + M*M)
dy = T * M / sqrt(1 + M*M)
원하는 점 1 = (PX + dx, PY + dy)
원하는 점 2 = (PX - dx, PY - dy)
왜 그런지는 좌표평면에 이 점들을 찍어본다음에 잘 생각해 보세요. 피타고라스의 정리만 있으면 됩니다.
다른 분들이 저렇게
다른 분들이 저렇게 답을 하니까 마치 위 공식은 다른 결과가 나오는 것처럼 되어 버렸는데요.
위 식을 정리하면 동일한 결과가 나옵니다.
식이 복잡해진 걸 정리하지 않아서 그럽니다.
어떤 방식으로 풀어도 결과는 같아야 합니다.
직선의 식은 아래와 같습니다.
y = m * x + c = m * x + Py - m * Px
위 식을 아래 식에 대입하면
T² = (x - Px)² + (y - Py)²
= (x - Px)² + (m * x + Py - m * Px - Py)²
= (x - Px)² + (m * x - m * Px)²
= (x - Px)² + m² * (x - Px)²
= (1 + m²) * (x - Px)²
가 되어
입니다.
어차피 삼각함수
어차피 삼각함수 자체가 거기서 나온것이므로 마찬가지는 맞습니다만,
특정 하드웨어의 경우 sin , cos 가 특별히 빠른케이스가 있습니다. 그래서 상황에 따라 같은 공식이지만 sin , cos 를 이용하면 전혀 다른 경우가 나올 수 있습니다.
심지어 일반 PC라도 cutomized math lib 을 쓰는 케이스에도 그냥 계산보다 sin , cos , arctan 이 빠를때도 있습니다.
그래서 하드웨어나 상황에 따라 sqrt 를 쓰거나 혹은 sin cos 를 사용하거나 하는건 테스트해보고 사용해보시라고 위에 적은 것 입니다.
Neogeo - Future is Now.
Neogeo - Future is Now.
전 프로그래머가 아니라서 그냥 수학식으로 풀어보았습니다.
직선과 엑스축이 이루는 각에 대한 탄젠트 값이 곧 기울기 입니다.
그리고 탄젠트 값은 사인값/코사인값 으로 나타낼 수 있습니다.
또한 사인값 제곱한 것과 코사인값 제곱한 것을 더하면 1이 되지요.
기울기 m= sin값/cos값 이므로 sin값 = m*cos값 입니다.
그러므로 (sin값)^ + (cos값)^ = m^(cos값)^ + (cos값)^ = (m^+1)*(cos값)^ = 1 이 됩니다.
따라서 cos값은 1/(m^+1) 에 루트를 씌운 겁니다. 이렇게 구한 걸 K 라고 하겠습니다.
sin값은 이렇게 구한 K 에 기울기 m 을 곱한 mK 가 되겠죠.
기울기가 m 인 직선상의 한 점 P(a,b)에서 거리 T 만큼 떨어진 같은 직선상의 점 Q를 구해보겠습니다.
아니면 원점을 지나는 기울기 m 인 직선 y=mx 와 원점이 중심인 원 x^+y^= T^ 이 만나는 점을 구한 후에 엑스축으로 a, 와이축으로 b 만큼 이동시켜도 됩니다.
ps.
루트 씌우는 거나 제곱표시같은 수식표현을 할 줄 몰라서 글로 쓰기가 참으로 힘드네요.
와우 많은 도움이 되었습니다. 감사합니다^^
와우 많은 도움이 되었습니다. 감사합니다^^
(px,py)를 중심으로 한
(px,py)를 중심으로 한 반지름 T인 원과 (px,py)를 지나고 기울기 M인 직선의 교차점;
다음 연립방정식을 푸세요.
(x-px)^2 + (y-py)^2 = T^2,
(y-py) = M*(x-px)
neogeo님이 쓴 방법을
neogeo님이 쓴 방법을 짧게 쓰면,,,
(T,0)을 M의 기울기를 갖도록 회전변환하고, -(px,py)만큼 평행이동합니다.
(x,y)=(T*cos(atan(M)+px,T*sin(atan(M)+py)
-T에 대해서도 똑같이 할 수 있겠군요.
삼각함수와 삼각함수 근사식의 cost를 비교해서 더 작은 cost가 드는 걸로 계산하면 되겠죠.
pamisu1 님이 쓰신 글도 참고해 보면 sin(atan(M))=M*cos(atan(M))
계산을 돌리는 것보다 메모리에 넣었다 읽어오는게 cost가 더 싸고, 삼각함수 계산보다 그냥 이항연산이 더 Cost가 싸다면 코드는 좀 길지만
정도가 되겠네요
--------------------------
snowall의 블로그입니다.
http://snowall.tistory.com
피할 수 있을때 즐겨라! http://melotopia.net/b
깔끔하지도 않고
깔끔하지도 않고 아티스틱하지도 않은...나름 몬테카를로 방법
그냥 대강의 코드 형태만 짜 봤습니다.
--------------------------
snowall의 블로그입니다.
http://snowall.tistory.com
피할 수 있을때 즐겨라! http://melotopia.net/b
이걸 몬테카를로
이걸 몬테카를로 방법이라고 하기는 좀...
그냥 눈감고 찍기네요.
앗, 들켰군요
앗, 들켰군요 -_-;
--------------------------
snowall의 블로그입니다.
http://snowall.tistory.com
피할 수 있을때 즐겨라! http://melotopia.net/b
이건...
이걸 국소탐색이라 봐야 하는건지 라스베가스 알고리즘이라고 봐야하는지 아시는 분 안계십니까?
Asche Zu Asche
눈감고 찍는게 Monte
눈감고 찍는게 Monte Carlo simulation의 기본 철학 아닌가요? :-)
물론 눈 뜨고 찍으면 더 좋을 때가 많습니다만.. (importance sampling)
----
Let's shut up and code.
----
Let's shut up and code.
자진삭제
.
댓글 달기