2011-05-12 4 views
1

I가 같은 선 A를 나타내는 두 개의 포인트가 있다고 가정는 결정

var A = [ { x: 385, y: 380 }, { x: 420, y: 400 }] 

및 I는 B 다른 두 지점을 가지고 C 등 :

var B = { x: 385, y: 420 } 
var C = { x: 405, y: 423 } 

B와 C가 둘 다 라인 A와 같은면에 있는지 어떻게 알 수 있습니까? 작은 컨텍스트를 추가하려면 B가 육각형의 중심점이고 C가 현재 마우스 위치이고 A가 육각형의 각 선인 육각형에 대한 적중 테스트를 수행하려고합니다. 이 모든 점은 본질적으로 0,0이 왼쪽 상단 구석 인 픽셀 좌표입니다.

필자는 빠른 속도로이 작업을 수행 할 필요가 없습니다. 가능한 가장 간단한 육각 충돌 테스트 알고리즘을 만들려고 노력하고 있습니다. 내 이론은 C가 B와 같은 육각형의 각 선과 같은면에 있다고 판단 할 수 있다면 히트 테스트가 성공적이라는 것입니다. 이 일을위한 몇 가지 수학적 알고리즘을 읽었지만, 그들은 항상 좌표계의 다른 유형에있는 것 같아요 그리고 나는 자바 스크립트에서 사용할 수있는 뭔가로 그것을 번역 고투하고 있어요.

편집 : 여기 실제 답변은 아래의 해답입니다. 이 질문에 대한 답은 업데이트 기능에 있습니다.

var TILE_WIDTH = 70 
var TILE_HEIGHT = 80 

function Hexagon(x, y) { 
    var normalColor = 'rgb(207, 226, 243)' 
    var hilightColor = 'rgb(204, 204, 204)' 
    var currentColor = normalColor 

    var coords = new TileCoordinates(x, y) 
    var points = [ 
     { x: coords.x, y: coords.y - TILE_HEIGHT/2 }, 
     { x: coords.x + TILE_WIDTH/2, y: coords.y - TILE_HEIGHT/4 }, 
     { x: coords.x + TILE_WIDTH/2, y: coords.y + TILE_HEIGHT/4 }, 
     { x: coords.x, y: coords.y + TILE_HEIGHT/2 }, 
     { x: coords.x - TILE_WIDTH/2, y: coords.y + TILE_HEIGHT/4 }, 
     { x: coords.x - TILE_WIDTH/2, y: coords.y - TILE_HEIGHT/4 }, 
    ] 

    var sides = [ 
     [points[0], points[1]], 
     [points[1], points[2]], 
     [points[2], points[3]], 
     [points[3], points[4]], 
     [points[4], points[5]], 
     [points[5], points[0]] 
    ] 

    this.update = function (totalTime, updateTime) { 

     var B = coords 
     var C = Mouse.state 
     var inside = C != null 
     if (inside) { 
      for (i in sides) { 
       var A = sides[i] 
       var w = { y: A[1].x - A[0].x, x: -(A[1].y - A[0].y) } 
       var P = A[1] 

       inside = ((B.x - P.x) * w.x + (B.y - P.y) * w.y) * ((C.x - P.x) * w.x + (C.y - P.y) * w.y) > 0 
       if (!inside) break 
      } 
     } 

     if (inside) 
      currentColor = hilightColor 
     else 
      currentColor = normalColor 
    } 

    this.draw = function (ctx) { 
     ctx.fillStyle = currentColor 
     ctx.strokeStyle = 'rgb(11, 83, 148)' 
     ctx.beginPath() 
     ctx.moveTo(points[0].x, points[0].y) 
     ctx.lineTo(points[1].x, points[1].y) 
     ctx.lineTo(points[2].x, points[2].y) 
     ctx.lineTo(points[3].x, points[3].y) 
     ctx.lineTo(points[4].x, points[4].y) 
     ctx.lineTo(points[5].x, points[5].y) 
     ctx.lineTo(points[0].x, points[0].y) 
     ctx.fill() 
     ctx.stroke() 

     ctx.fillStyle = '#000' 
     var text = coords.pos_x + ',' + coords.pos_y 
     var measure = ctx.measureText(text) 
     ctx.fillText(text, coords.x - measure.width/2, coords.y + 12 + (TILE_HEIGHT/4)) 
    } 
} 

// this is in a separate function because other objects that render into the hex 
// need the pixel coordinates of the tile also 
function TileCoordinates(x, y) { 
    this.pos_x = x 
    this.pos_y = y 
    this.x = x * TILE_WIDTH + ((y + 1) * TILE_WIDTH/2) 
    this.y = (y + 1) * (3/4 * TILE_HEIGHT) 
} 

나는 B 및 C의 결과를 승산 동일한 일면성을 결정하고, 그 결과는> 0 인 경우, 그들은 포지티브 또는 네거티브 양쪽 모두. setInterval을 사용하여 육각형을 캔버스로 렌더링하고 업데이트하고 있습니다.

+0

선택한 알고리즘을 게시하지 않으려면 찾은 링크를 게시하십시오. 내 머리 꼭대기에서 선이 AB이고 점이 C와 D이면 각도 ABD와 ABC가 둘 다 180보다 크거나 둘 다 180보다 작 으면 D와 C는 "같은쪽에"있습니다. – RobG

+1

질문에 정확하게 답변하지는 않지만 http://stackoverflow.com/questions/217578/point-in-polygon-aka-hit-test에는 일반적으로 폴리곤 히트 테스트에 대한 몇 가지 좋은 답변이 있습니다. – servn

+0

[포인트가 라인의 오른쪽 또는 왼쪽에 있는지 알려주는 방법] 가능한 복제본 (http://stackoverflow.com/questions/1560492/how-to-tell-wether-a-point-is-right-or- left-of-a-line) –

답변

6

A를 나타내는 선은 벡터 v = { x: 420 - 385, y: 400 - 380 } = { x: 35, y: 20 } 및 시작점 P = { x: 385, y: 380 }으로 설명됩니다. 2 차원에서 벡터 (x, y)이 주어지면 벡터 (y, -x)은 항상 그것에 직각을 이룹니다. 따라서 벡터 w = { x: 20, y: -35 }v에 직각입니다. 선형 대수학은 (B - P) dot w의 부호가 당신이 어느 선에 있는지 알려줍니다. dot은 표준 내적입니다. (라인 자체는 제로입니다.)

따라서 귀하의 예제에서 우리가해야 할 계산은 이것이다 : 부호가 동일

For B: 
(B - P) dot w 
    = { x: 385 - 385, y: 420 - 380 } dot { x: 20, y: -35 } 
    = { x: 0, y: 40} dot { x: 20, y: -35 } 
    = (0 * 20) + (40 * (-35)) 
    = -1400 

For C: 
(C - P dot w 
    = { x: 405 - 385, y: 423 - 380 } dot { x: 20, y: -35 } 
    = { x: 20, y: 43} dot { x: 20, y: -35 } 
    = (20 * 20) + (43 * (-35)) 
    = -1105 

때문에,이 같은 측면에 있습니다.

실제로 우리는 더 말할 수 있습니다. A의 시작 지점에 있고 끝 지점을 마주하고 있다면 두 지점 모두 왼편에 있습니다. (왼쪽은 음수, 오른쪽은 양수입니다.)

+0

아름답습니다. OP는 일반적인 경우에 프로그래밍 만하면됩니다. 측량 배경을 가지고 각도를 사용하여 해결했지만 솔루션은 훨씬 더 우아합니다.물론 알고리즘을 집어 넣어도 괜찮 으면 좋겠다. :-) – RobG

+0

아, 한 가지 추가 사항 - OP는 실제로 어느 지점이 라인에 있는지 (또는 ECMAScript 번호의 작은 부정확성을 고려하면 극도로 가깝습니다) 테스트해야하며 그 의미에 대한 결정을 내립니다. 한 점이 선상에 있다면 결과가 같은면이 아닌 동일한면에 있거나 정의되지 않았습니까? – RobG

+1

@RobG - 귀찮게하지 마세요. 그것은 표준 기술입니다. :-) – btilly