2015-01-30 1 views
1

원래 같은 선상에없는 세 점이 있습니다. 원래이 세 점을 통해 원호를 그립니다. 그러나 크롬은 실제 원을 그린 것이 아니라 베 지어 곡선이 저렴하기 때문에 여러 개의 베 지어 곡선을 사용하여 원을 가장합니다. 크롬이 중간 남자로서 그것을하고 있다면, 왜 내가 원과 같은 베 지어를 그리지 않는 것일까? (1 점에서 중간 점, 중간 점에서 3 점으로 두 베 지어)? 그것은 훨씬 더 깔끔하고 저렴합니다 (2 개의 베지에 곡선 (Bezier Curve) 브라우저가 결정한 알려지지 않은 수에 비해). 그게 내가 붙어있는 곳이야, 어떻게? "통제 지점"은 어디에 있어야합니까? 여기원호를 모방하기 위해 3 개의 점을 통과하는 2 개의 베 지어 커브를 그립니다.

내 오래된 무승부 아크 기능입니다 자바 스크립트

drawArc = function(startPoint, thirdPoint, endPoint){ 
var ctx = this.ctx; 
ctx.lineWidth = this.strokeWidth; 
ctx.strokeStyle = this.strokeColor; 

var centerObject = circleCenter(new Point(startPoint.x, startPoint.y), 
           new Point(thirdPoint.x, thirdPoint.y), 
           new Point(endPoint.x, endPoint.y)); 
var centerX = centerObject.x; 
var centerY = centerObject.y; 
var r = centerObject.r 

var angle = Math.atan2(centerX-startPoint.x, centerY-startPoint.y); 
// console.log(centerObject); 
if (!angle){ 
    ctx.beginPath(); 
    ctx.moveTo(startPoint.x, startPoint.y); 
    ctx.lineTo(endPoint.x, endPoint.y); 
} else { 
    if(angle > Math.PI/2) { 
     ctx.beginPath(); 
     ctx.arc(centerX, centerY, r, Math.PI * 1.5-angle, Math.PI * 1.5 + angle, true); 
    } else { 
     ctx.beginPath(); 
     ctx.arc(centerX, centerY, r, Math.PI * 1.5-angle, Math.PI * 1.5 + angle, false); 
    } 
} 
ctx.globalCompositeOperation = "source-over"; 
ctx.stroke(); 

} 
var circleCenter = function(startPoint, thirdPoint, endPoint){ 
var dy1 = thirdPoint.y - startPoint.y; 
var dx1 = thirdPoint.x - startPoint.x; 
var dy2 = endPoint.y - thirdPoint.y; 
var dx2 = endPoint.x - thirdPoint.x; 

var aSlope = dy1/dx1; 
var bSlope = dy2/dx2; 


var centerX = (aSlope*bSlope*(startPoint.y - endPoint.y) + bSlope*(startPoint.x + thirdPoint.x) 
    - aSlope*(thirdPoint.x+endPoint.x))/(2* (bSlope-aSlope)); 
var centerY = -1*(centerX - (startPoint.x+thirdPoint.x)/2)/aSlope + (startPoint.y+thirdPoint.y)/2; 
var r = dist(centerX, centerY, startPoint.x, startPoint.y) 

return { 
    x: centerX, 
    y: centerY, 
    r: r 
}; 
} 

누군가가) (나() 메소드 대신에 아크 후에 bezierCurveTo 캔버스 사용 drawArc 기능을 다시 도와 드릴까요?

내 코드 예제는 여기에 있습니다 : http://codepen.io/wentin/pen/VYegqq

+0

"베 지어 커브는 싸다": 작은 커브는 원형 아크에 비해 베 지어 커브는 * 미친 듯이 비싼 * 그릴 수 있습니다. 하나의 베 지어 세그먼트를 계산하고 그릴 필요가있을 때 동시에 여러 번 세 점을 통해 원호를 찾아 그릴 수 있습니다. Canvas2d의'arc()'명령은 내가 아는 바로는 베 지어 근사가 아닌 진정한 원호입니다. –

답변

3

당신은 4 개 차 베 지어 곡선을 사용하여 원에 근접 할 수 있습니다 ...하지만 완벽한 원 ;-)

enter image description here

예제 코드이 아니다 및 데모 :

반경 & 상수 c 사이의 관계를 시작, 끝 및 제어 지점까지 사용할 수 있습니다. 원하는 제어점을 계산하십시오. 이 베 지어 근사 원은 원점 [0,0] 주위에 그려 지므로 물론 원의 특정 중심점으로 변환됩니다.

var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 

 
ctx.lineWidth=3; 
 

 
// refined from 0.551915024494 thanks to Pomax 
 
var c=0.5522847498307933984022516322796 ; 
 

 
var cx=150; // center x 
 
var cy=150; // center y 
 
var r=100; // radius 
 

 
drawBezierCircle(cx,cy,r); 
 

 
function drawBezierCircle(cx,cy,r){ 
 
    
 
    ctx.translate(cx,cy); // translate to centerpoint 
 

 
    ctx.beginPath(); 
 

 
    ctx.moveTo(0,-r); 
 
    ctx.bezierCurveTo(
 
     c*r,-r, 
 
     r,-c*r, 
 
     r,0 
 
    ); 
 
    ctx.strokeStyle='red'; 
 
    ctx.stroke(); 
 

 
    ctx.beginPath(); 
 
    ctx.moveTo(r,0); 
 
    ctx.bezierCurveTo(
 
     r,c*r, 
 
     c*r,r, 
 
     0,r 
 
    ); 
 
    ctx.strokeStyle='green'; 
 
    ctx.stroke(); 
 

 
    ctx.beginPath(); 
 
    ctx.moveTo(0,r); 
 
    ctx.bezierCurveTo(
 
     -c*r,r, 
 
     -r,c*r, 
 
     -r,0 
 
    ); 
 
    ctx.strokeStyle='blue'; 
 
    ctx.stroke(); 
 

 
    ctx.beginPath(); 
 
    ctx.moveTo(-r,0); 
 
    ctx.bezierCurveTo(
 
     -r,-c*r, 
 
     -c*r,-r, 
 
     0,-r 
 
    ); 
 
    ctx.strokeStyle='gold'; 
 
    ctx.stroke(); 
 
}
body{ background-color: ivory; padding:10px; } 
 
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>

+1

변수'c' (일반적으로 사용 된 수학 이름을 나타 내기 위해'k'라고 쓰여진'kappa')는 0.5522847498307933984022516322796이어야합니다 (또는 반올림하지 않고 4 * (sqrt (2) -1)/3). http://pomax.github.io/bezierinfo/#circles_cubic –

+0

@ Mike'Pomax'Kamermans, 충분히보기 ... 0.5522847498307933984022516322796입니다! BTW, 나는 베지에 곡선에 대한 논문에서 많은 것을 즐겁게 배웠습니다 - 그것을 써 주셔서 감사합니다! http://pomax.github.io/bezierinfo/ – markE

+1

언제나 유용하다는 소식을 듣고 기뻐했습니다. =) –

1

넌 단부 점 P0, P1, 반지름 R 및 각도 폭 A를 갖는 원호로 근사하는 큐빅 베 지어 곡선의 제어점을 찾기 위해 다음과 같은 방법을 사용할 수

다음 Q0, Q1, Q2 및 Q3과 같은 제어 포인트를 나타내는

Q0 = P0,
Q3 = P1, Q1 =
P0 + L * T0
Q2 = P1 - L의 * T1 T0 및 T1이 P0와 P1 및 L = (4/3) * 황갈색 (A/4의 원호의 단위 접선 벡터이다

).

각도 스팬 A가 커지면 근사 오차가 커집니다. 따라서 3 점으로 정의 된 원호의 각도 스팬이 비교적 작 으면 하나의 3 차 베 지어 곡선을 사용하여 정밀한 정밀도로 근사시킬 수도 있습니다. 마찬가지로 원 호를 근사하기 위해 항상 두 개의 베 지어 곡선 (각 두 점 사이에 하나의 곡선)을 사용하면 좋지 않은 근사로 끝날 수 있습니다. Chrome이 여러 개의 베 지어 곡선을 사용하여 원호를 그리는 경우 정밀도가 베 지어 곡선의 수가 고정 값이 아닌 이유 일 수 있습니다.

+0

감사합니다. 정말 도움이되었습니다. –

+0

도움이된다는 것을 알고 기쁘게 생각합니다. – fang

관련 문제