2011-01-15 5 views
0

주어진 원에 대해 모든 점 좌표가 차례로 있어야하므로 한 점에서 다음 점으로 호핑하여 객체를 원으로 만들 수 있습니다. Midpoint circle 알고리즘을 시도했지만 찾은 버전은 그려야하며 좌표는 순차적이지 않습니다. 그것들은 동시에 8 사분면과 반대 방향으로 동시에 생산됩니다. 만약 그들이 적어도 같은 방향이라면, 나는 모든 사분면에 대해 별도의 배열을 만들고, 그 끝에 서로를 추가 할 수 있습니다. 이것은 자바 스크립트 내가 지금 가지고 코드 적응 : 순차 좌표를 순차적으로 계산합니다.

function calcCircle(centerCoordinates, radius) { 
    var coordinatesArray = new Array(); 
    // Translate coordinates 
    var x0 = centerCoordinates.left; 
    var y0 = centerCoordinates.top; 
    // Define variables 
    var f = 1 - radius; 
    var ddFx = 1; 
    var ddFy = -radius << 1; 
    var x = 0; 
    var y = radius; 
    coordinatesArray.push(new Coordinates(x0, y0 + radius)); 
    coordinatesArray.push(new Coordinates(x0, y0 - radius)); 
    coordinatesArray.push(new Coordinates(x0 + radius, y0)); 
    coordinatesArray.push(new Coordinates(x0 - radius, y0)); 
    // Main loop 
    while (x < y) { 
     if (f >= 0) { 
     y--; 
     ddFy += 2; 
     f += ddFy; 
     } 
     x++; 
     ddFx += 2; 
     f += ddFx; 
     coordinatesArray.push(new Coordinates(x0 + x, y0 + y)); 
     coordinatesArray.push(new Coordinates(x0 - x, y0 + y)); 
     coordinatesArray.push(new Coordinates(x0 + x, y0 - y)); 
     coordinatesArray.push(new Coordinates(x0 - x, y0 - y)); 
     coordinatesArray.push(new Coordinates(x0 + y, y0 + x)); 
     coordinatesArray.push(new Coordinates(x0 - y, y0 + x)); 
     coordinatesArray.push(new Coordinates(x0 + y, y0 - x)); 
     coordinatesArray.push(new Coordinates(x0 - y, y0 - x)); 
    } 
    // Return the result 
    return coordinatesArray; 
    } 

내가 삼각법없이 어떤 빠른 알고리즘을 선호하는,하지만 어떤 도움이 감사합니다!

EDIT

이 최종 솔루션이다. 감사합니다 여러분!

function calcCircle(centerCoordinates, radius) { 
    var coordinatesArray = new Array(); 
    var octantArrays = 
     {oct1: new Array(), oct2: new Array(), oct3: new Array(), oct4: new Array(), 
     oct5: new Array(), oct6: new Array(), oct7: new Array(), oct8: new Array()}; 
    // Translate coordinates 
    var xp = centerCoordinates.left; 
    var yp = centerCoordinates.top; 
    // Define add coordinates to array 
    var setCrd = 
     function (targetArray, xC, yC) { 
     targetArray.push(new Coordinates(yC, xC)); 
     }; 
    // Define variables 
    var xoff = 0; 
    var yoff = radius; 
    var balance = -radius; 
    // Main loop 
    while (xoff <= yoff) { 
     // Quadrant 7 - Reverse 
     setCrd(octantArrays.oct7, xp + xoff, yp + yoff); 
     // Quadrant 6 - Straight 
     setCrd(octantArrays.oct6, xp - xoff, yp + yoff); 
     // Quadrant 3 - Reverse 
     setCrd(octantArrays.oct3, xp - xoff, yp - yoff); 
     // Quadrant 2 - Straight 
     setCrd(octantArrays.oct2, xp + xoff, yp - yoff); 
     // Avoid duplicates 
     if (xoff != yoff) { 
     // Quadrant 8 - Straight 
     setCrd(octantArrays.oct8, xp + yoff, yp + xoff); 
     // Quadrant 5 - Reverse 
     setCrd(octantArrays.oct5, xp - yoff, yp + xoff); 
     // Quadrant 4 - Straight 
     setCrd(octantArrays.oct4, xp - yoff, yp - xoff); 
     // Quadrant 1 - Reverse 
     setCrd(octantArrays.oct1, xp + yoff, yp - xoff); 
     } 
     // Some weird stuff 
     balance += xoff++ + xoff; 
     if (balance >= 0) { 
     balance -= --yoff + yoff; 
     } 
    } 
    // Reverse counter clockwise octant arrays 
    octantArrays.oct7.reverse(); 
    octantArrays.oct3.reverse(); 
    octantArrays.oct5.reverse(); 
    octantArrays.oct1.reverse(); 
    // Remove counter clockwise octant arrays last element (avoid duplicates) 
    octantArrays.oct7.pop(); 
    octantArrays.oct3.pop(); 
    octantArrays.oct5.pop(); 
    octantArrays.oct1.pop(); 
    // Append all arrays together 
    coordinatesArray = 
     octantArrays.oct4.concat(octantArrays.oct3).concat(octantArrays.oct2).concat(octantArrays.oct1). 
     concat(octantArrays.oct8).concat(octantArrays.oct7).concat(octantArrays.oct6).concat(octantArrays.oct5); 
    // Return the result 
    return coordinatesArray; 
    } 
+1

브라우저의 순환 경로에서 개체를 이동하려는 경우 문제의 LAST는 sin/cos의 속도와 관련됩니다. – 6502

+1

나는 정확하게이 이유 때문에 객체가 사용할 좌표를 미리 계산할 것이고 객체는 실제로 많은 객체이다. 그래서 sin/cos의 속도가 걱정 될 수 있습니다. 특히 Netbook에 IE가있는 경우. –

+0

sin/cos의 또 다른 단점은 유한 수의 점을 생성한다는 것입니다. 원의 반지름이 증가함에 따라 계산되는 점의 수가 동일하면 (원주상의 간격이 증가하기 때문에) 렌더링되는 항목의 겉보기 속도가 증가합니다. – Bob

답변

1

사용하지 않고 데이브의 첫 번째 대답을 활용. 그 다음에 (x0 + x, y0-y), (x0-x, y0 + y), (x0 + y, y0 + x), (x0-y, y0-x)) 그리고 나서 모든 배열을 올바른 순서로 추가하십시오. 첫 번째 네 점을 올바른 배열에 추가해야합니다.

+0

나는 그것도 생각했다. 나는 당신을 때렸지 만, 여전히 당신에게 크레딧을 준다;) 또 다른 해결책은 오직 하나의 8 분면 대신에 엔트 서클을 계산하는 것이지만 알고리즘을 어떻게 적응 시킬지 모른다. –

1

내가 아는 한, 당신은 삼각법 없이는 할 수 없지만, 그것은 나를 위해 꽤 빨리 작동합니다. 죄송합니다 제가 자바에 익숙하지 않은, 그래서 내가 VB에서 코드를 작성 :


Dim PointList As New List(Of PointF) 
For angle = 0 To Math.PI * 2 Step 0.01 
    'the smaller the step, the more points you get 
    PointList.Add(New PointF(Math.Cos(angle) * r + x0, Math.Sin(angle) * r + y0)) 
Next 

X0 및 Y0가 중심이 원의 좌표이며, r은 반경이다.

희망 사항 귀하의 질문에 답변했습니다.

+1

적어도 이것이 원의 반경없이 어떻게 작동하는지 궁금합니다. – Hemlock

+0

주의 해 주셔서 감사합니다. 코드를 편집했습니다. – Dave

0

다음은 Dave의 대답을 기반으로 한 자바 스크립트 구현입니다. 조금 지나치게 설계되었으므로 필자는 죄와 코사인을 필요 이상으로 부르는 것을 피하고 싶었다. 당신이 준 알고리즘을 사용하지만 8 개의 서로 다른 coordinateArrays에 좌표를 밀어 : 아이러니하게도 반경 : 다음과 같은 방법을 시도 할 수 있습니다

function calculateCircle(x,y,radius) { 

    var basicPoints = getBasicCircle(); 
    var i = basicPoints.length; 
    var points = []; // don't change basicPoints: that would spoil the cache. 
    while (i--) { 
    points[i] = { 
     x: x + (radius * basicPoints[i].x), 
     y: y + (radius * basicPoints[i].y) 
    }; 
    } 
    return points; 
} 

function getBasicCircle() { 
    if (!arguments.callee.points) { 
    var points = arguments.callee.points = []; 
    var end = Math.PI * 2; 
    for (var angle=0; angle < end; angle += 0.1) { 
     points.push({x: Math.sin(angle), 
        y: Math.cos(angle) 
        }); 
    } 
    } 
    return arguments.callee.points 
} 
+0

감사합니다 독 당근! 네가 한 일에 대해 더 자세히 설명해 주겠니? 미리 계산 된 원의 왕을 사용하고 다른 반지름으로 확장 하시겠습니까? 큰 원을 그리기에 포인트가 충분하지 않은 경우이 작업은 효과가 없을 것입니다. –

+0

예, 반경 1의 원을 사전 계산합니다. 더 높거나 낮은 해상도로 원을 반환하려면 캐싱 기능을 변경해야합니다. – Hemlock