2013-07-30 3 views
0

원 c1이 다른 원 c2 안에 완전히 있도록 수학적 절차를 구현하려고합니다.기능은 원과 교정 내에서 원입니까?

그것은 다음과 같은 방식으로 작동한다 :

주어 C1 (X, Y, R) 및 (C2) (X, Y, R) 및 경우 c2.r> c1.r

  • 참을 리턴 c1이 c2 내부에 있음
  • 벡터를 반환하여 c1에 적용 할 최소 보정 값 인 벡터 V (x, y)를 반환하므로 c2 내부에 있습니다.

어떻게 보입니까? 수학자 나 물리학 자에게는 쉬워야하지만 나에게는 꽤 어렵다.

이미 lua에서 구현을 시도했지만 분명히 잘못되었습니다.

local function newVector(P1, P2) 
    local w, h=(P2.x-P1.x), (P2.y-P1.y) 
    local M=math.sqrt(w^2 + h^2) 
    local alpha=math.atan(h/w) 
    return {m=M, alpha=alpha} 
end 

local function isWithin(C1, C2) 
    local V12=newVector(C1, C2) 
    local R12=C2.r-C1.r 
    local deltaR=R12-V12.m 
    if deltaR>=0 then 
     return true 
    else 
     local correctionM=(V12.m+deltaR) --module value to correct 
     local a=V12.alpha 
     print("correction angle: "..math.deg(a)) 
     local correctionX=correctionM*math.cos(a) 
     local correctionY=correctionM*math.sin(a) 
     return {x=correctionX, y=correctionY} 
    end 
end 

고마워요!

+1

아마도 'math.atan2'를 사용해야합니다. – lhf

+0

어떤 종류의 수정을 의미합니까? 센터 번역? 반경의 척도? 양자 모두? – lhf

+0

나는 원 1의 번역을 의미하므로 C1에 반환 된 벡터 V (x, y)를 더하면 C1이 C2 안에있게됩니다. 예를 들어 C1이 2 픽셀 오른쪽 및 1 픽셀 아래로 C2를 벗어난 경우 반환 값은 {x = -2, y = -1}이어야합니다. – nest

답변

1

해당 거리 (Center1, Center2) + Radius1을 확인하는 것으로 충분하지 않습니다. < = Radius2?

local function isWithin(C1, C2) 
    local distance = math.sqrt((C1.x-C2.x)^2+(C1.y-C2.y)^2) 
    return distance + C1.r <= C2.r + Epsilon 

엡실론 수치 오류를 방지하기 위해 사용된다. (예 : Epsilon = 1e-9)

쉬운 소리입니다.

+1

'엡실론'이란 무엇입니까? – lhf

+0

숫자 오류가있는 경우. 응답에 추가했습니다. – David

+0

@David 네, 그 정도면 충분합니다. 서클은 결국 매우 단순한 (수학적) 형태입니다. 그러나 보정 벡터는 조금 더 복잡합니다. 너무 많지는 않지만 – dualed

0

좋아, 마침내 제대로 작동합니다.

열쇠는 lhf가 제안한대로 math.atan2를 사용하는 것이 었습니다. 보정 값에 몇 가지 실수가있었습니다.

여기에 최종 코드가 있습니다. 또한 코로나 표시 객체에서 원을 만들 때 사용하는 circleFromBounds 함수도 포함 시켰습니다.

local function newVector(P1, P2) 
    local w, h=(P2.x-P1.x), (P2.y-P1.y) 
    local M=math.sqrt(w^2 + h^2) 
    local alpha=math.atan2(h, w) 
    return {m=M, alpha=alpha} 
end 

local function isWithin(C1, C2) 
    local V12=newVector(C1, C2) 
    local epsilon = 10^(-9) 
    if (V12.m + C1.r <= C2.r + epsilon) then 
     return true 
    else 
     local correctionM=(C2.r-(C1.r+V12.m)) --module value to correct 
     local A=V12.alpha 
     local correctionX=correctionM*math.cos(A) 
     local correctionY=correctionM*math.sin(A) 
     return {x=correctionX, y=correctionY} 
    end 
end 

local function circleFromBounds(bounds, type) 
    local x, y, r 
    local width, height = (bounds.xMax-bounds.xMin), (bounds.yMax-bounds.yMin) 
    local ratio=width/height 

    x=bounds.xMin+width*.5 
    y=bounds.yMin+height*.5 

    if "inner"==type then 
     if ratio>1 then 
      r=height*.5 
     else 
      r=width*.5 
     end 
    elseif "outer"==type then 
     local c1, c2 = width*.5, height*.5 
     r = math.sqrt(c1^2 + c2^2) 
    end 

    return {x=x, y=y, r=r} 
end 

도움 주셔서 감사합니다.