2013-08-05 3 views
1

그리기 응용 프로그램의 경우 마우스 이동 좌표를 배열에 저장 한 다음 lineTo로 그 좌표를 그립니다. 결과 선이 매끄럽지 않습니다. 어떻게 모든 모아진 점 사이에 하나의 곡선을 만들 수 있습니까?자바 스크립트 HTML5 캔버스를 사용하여 N 포인트를 통해 곡선을 그리는 방법?

나는 봤지만 줄을 그리기위한 3 가지 함수 만 찾았습니다. 2 개의 샘플 점에 대해 간단하게 lineTo를 사용하십시오. 3 샘플 포인트 quadraticCurveTo, 4 샘플 포인트, bezierCurveTo.

(대신 연속적인 매끄러운 곡선의 매 4 샘플 포인트 I 어레이의 각 4 점에 대해 후에 bezierCurveTo 드로잉했지만, 이것에 꼬임을 이끈다.)

어떻게 매끄러운 그릴 함수를 작성 않는다 5 개의 샘플 포인트와 그 이상의 곡선? 이렇게하는 기수 스플라인을 사용

+0

켄은 괜찮은 답변을했습니다. 이 속성 (점을 통과하는 스플라인)에 대한 자세한 내용을 보려면 "유한 차분 곡선", "기본 스플라인", "Catmull-Rom 스플라인"및 "Kochanek-Bartels 스플라인"이라는 용어를 찾아보십시오. –

답변

1

:

각 사이의 해상도를 지시이를위한 기능은 [0.0, 1.0] 및 세그먼트들의 임의 수 사이 [x1, y1, x2, y2, ... xn, yn] 주문할 점 배열 장력이 같다

포인트.

- 결과는 당신이 반복 스무딩 줄 새로운 배열 될 것입니다

-

Here's an online demo of this in action

UPDATE 내 추기경 구현의 잘못된 버전을 기록,이 올바른 하나입니다

function getCurvePoints(ptsa, tension, numOfSegments) { 

    // use input value if provided, or use a default value 
    tension   = (tension != 'undefined') ? tension : 0.5; 
    numOfSegments = numOfSegments ? numOfSegments : 16; 

    var _pts = [], res = [], // clone array 
     x, y,     // our x,y coords 
     t1x, t2x, t1y, t2y,  // tension vectors 
     c1, c2, c3, c4,   // cardinal points 
     st, t, i;    // steps based on num. of segments 

    // clone array so we don't change the original 
    _pts = ptsa.slice(0); 

    _pts.unshift(pts[1]);   //copy 1. point and insert at beginning 
    _pts.unshift(pts[0]); 
    _pts.push(pts[pts.length - 2]); //copy last point and append 
    _pts.push(pts[pts.length - 1]); 

    // ok, lets start.. 

    // 1. loop goes through point array 
    // 2. loop goes through each segment between the two points + one point before and after 
    for (i=2; i < (_pts.length - 4); i+=2) { 

     // calc tension vectors 
     t1x = (_pts[i+2] - _pts[i-2]) * tension; 
     t2x = (_pts[i+4] - _pts[i]) * tension; 

     t1y = (_pts[i+3] - _pts[i-1]) * tension; 
     t2y = (_pts[i+5] - _pts[i+1]) * tension; 

     for (t=0; t <= numOfSegments; t++) { 

      // calc step 
      st = t/numOfSegments; 

      // calc cardinals 
      c1 = 2 * Math.pow(st, 3) - 3 * Math.pow(st, 2) + 1; 
      c2 = -(2 * Math.pow(st, 3)) + 3 * Math.pow(st, 2); 
      c3 =  Math.pow(st, 3) - 2 * Math.pow(st, 2) + st; 
      c4 =  Math.pow(st, 3) -  Math.pow(st, 2); 

      // calc x and y cords with common control vectors 
      x = c1 * _pts[i] + c2 * _pts[i+2] + c3 * t1x + c4 * t2x; 
      y = c1 * _pts[i+1] + c2 * _pts[i+3] + c3 * t1y + c4 * t2y; 

      //store points in array 
      res.push(x); 
      res.push(y); 

     } 
    } 

    return res; 
} 
+0

"세그먼트 수"인수가 필요하지 않아야하며, 스플라인은 연속 커브이며 낮은 복잡성에서 포인트 생성을 통해 실행하는 것은 순수한 번호 계산입니다. JS가 잘 수행합니다. –

+0

@ Mike'Pomax'Kamermans 세그먼트 값이 필요하기 때문에 각 초기 점 사이에 플롯해야하는 점의 수를 알아야합니다. – K3N

+0

일 필요는 없습니다. "얼마나 많은 세그먼트"가 아닌, 스플라인 탄젠트를 기반으로 다음 좌표를 얻는 것이 더 쉽습니다. 강한 탄젠트는 다음 점이 떨어져있는 간격이 짧아야한다는 것을 의미하며, 약한 탄젠트는 더 큰 간격을 사용할 수 있음을 의미합니다. 이렇게하면 N 개의 세그먼트를 필요로하는 것부터 시작하는 것보다 더 나은 곡선 근사를 생성 한 다음 고정 간격 폴링을 사용하여 생성합니다 –