將如圖1所示的上邊長方形的圖形變換爲下邊的扇形圖形的變換稱爲扇形變換。javascript
設長方形圖形中任一點P1(X1,Y1)變換爲扇形圖形上的點P2(X2,Y2),長方形的長爲X,扇形圓心座標爲(X0,Y0),扇形半徑爲L,扇形與X軸的最小夾角爲B,扇形弧對應夾角爲C,則點P2的座標計算公式爲:html
X2=(L+Y1)*COS(θ)+X0java
Y2=-(L+Y1)*SIN(θ)+Y0canvas
其中: θ=C*(X-X1)/X1+B數組
圖1 扇形變換瀏覽器
生成一個六瓣花型圖案的基本數據,將長方形中的8個六瓣花型做爲基本圖案,進行指定層數的扇形變換。3d
編寫以下的HTML代碼。orm
<!DOCTYPE html>htm
<head>blog
<title>扇形變換</title>
<script type="text/javascript">
function drawBase(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,700,100);
context.fillStyle="yellow";
context.strokeStyle="red";
context.lineWidth=2;
context.beginPath();
var dig=Math.PI/64;
var x=new Array();
var y=new Array();
var w=80;
// 生成一個六瓣花型圖案的數據
for (var i=0;i<=128;i++)
{
d=w/2*(0.8+Math.sin(18*i*dig)/5)*1.2;
t=d*(0.5+Math.sin(6*i*dig)/2);
x[i]=t*Math.cos(i*dig);
y[i]=t*Math.sin(i*dig);
}
// 在水平一行中繪製8個六瓣花型圖案
for (n=1;n<=8;n++)
{
px=(2*n-1)/2*w+30;
for (i=0;i<=128;i++)
{
x1=px+x[i];
y1=w/2-y[i];
if (i==0)
{
context.moveTo(x1,y1);
bx=x1; by=y1;
}
else
context.lineTo(x1,y1);
}
}
context.lineTo(bx,by);
context.closePath();
context.stroke();
context.fill();
}
function drawSector(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,700,500);
context.fillStyle="yellow";
context.strokeStyle="red";
context.lineWidth=2;
context.beginPath();
var dig=Math.PI/64;
w=80;
var x=new Array();
var y=new Array();
// 生成一個六瓣花型圖案的數據
for (var i=0;i<=128;i++)
{
d=w/2*(0.8+Math.sin(18*i*dig)/5)*1.2;
t=d*(0.5+Math.sin(6*i*dig)/2);
x[i]=t*Math.cos(i*dig);
y[i]=t*Math.sin(i*dig);
}
var k=eval(document.myForm.levelNum.value);
if (k<1 || k>=6) {
alert("扇形層數需設定爲1~5之一!");
return;
}
// 進行多重扇形變換
l=100; b=Math.PI/3; c=Math.PI/3; x0=350; y0=500;
for (m=1;m<=k;m++)
for (n=1;n<=8;n++)
for (var i=0;i<=128;i++)
{
px=(2*n-1)/2*w;
py=(2*m-1)/2*w;
x1=px+x[i];
y1=py-y[i];
th=c*(w*8-x1)/(w*8)+b;
x2=(l+y1)*Math.cos(th)+x0;
y2=-(l+y1)*Math.sin(th)+y0;
if (i==0)
{
context.moveTo(x2,y2);
bx=x2; by=y2;
}
else
context.lineTo(x2,y2);
}
context.lineTo(bx,by);
context.closePath();
context.stroke();
context.fill();
}
</script>
</head>
<body onload="drawBase('myCanvas1');">
基本圖案<br/>
<canvas id="myCanvas1" width="700" height="100">您的瀏覽器不支持canvas!</canvas>
<form name="myForm">
扇形中基本圖案層次數<input type=number name="levelNum" value=4 size=3>
<input type=button value="肯定" onClick="drawSector('myCanvas2');">
</form><br>
<canvas id="myCanvas2" width="700" height="500">您的瀏覽器不支持canvas!</canvas>
</body>
</html>
將上述HTML代碼保存到一個html文本文件中,再在瀏覽器中打開包含這段HTML代碼的html文件,在「扇形中基本圖案層次數」數值框中輸入「5」,單擊「肯定」按鈕,能夠在瀏覽器窗口中看到基本六瓣花型圖案的5層扇形變換,如圖2所示。
圖2 扇形變換
將如圖3所示的上邊長方形帶狀圖形變換爲下邊的環狀圖形的變換稱爲環形變換。環狀變換將帶狀圖的左右兩端接在一塊兒,於是帶狀圖的上部被拉伸,下部被壓縮。
設帶狀圖形中任一點P1(X1,Y1)變換爲環狀圖形上的點P2(X2,Y2),帶狀長方形的長爲X,環狀圖形的圓心座標爲(PX,PY),L爲環形內半徑(L的值越小,變換後圖案的變形越大),則點P2的座標計算公式爲:
X2=(L+Y1)*COS(θ)+PX
Y2=-(L+Y1)*SIN(θ)+PY
其中: θ=2π*(X-X1)/X
圖3 環形變換
按環形變換的方法將如圖4所示的基本圖案進行環形變換。
圖4 用於環形變換的基本圖案
編寫以下的HTML代碼。
<!DOCTYPE html>
<head>
<title>環形變換</title>
<script type="text/javascript">
function draw1(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,800,500);
context.fillStyle="yellow";
context.strokeStyle="red";
context.lineWidth=1;
context.beginPath();
var dig=Math.PI/64;
var x=new Array();
var y=new Array();
var w=100;
// 生成一個六瓣花型圖案的數據
for (var i=0;i<=128;i++)
{
d=w/2*(0.8+Math.sin(18*i*dig)/5)*1.2;
t=d*(0.5+Math.sin(6*i*dig)/2);
x[i]=t*Math.cos(i*dig);
y[i]=t*Math.sin(i*dig);
}
// 在水平一行中繪製8個六瓣花型圖案
for (n=1;n<=8;n++)
{
px=(2*n-1)/2*w;
for (i=0;i<=128;i++)
{
x1=px+x[i];
y1=w/2-y[i];
if (i==0)
{
context.moveTo(x1,y1);
bx=x1; by=y1;
}
else
context.lineTo(x1,y1);
}
}
context.lineTo(bx,by);
context.closePath();
context.stroke();
context.fill();
}
function draw2(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,800,500);
context.fillStyle="yellow";
context.strokeStyle="red";
context.lineWidth=2;
context.beginPath();
var dig=Math.PI/64;
var x=new Array();
var y=new Array();
var w=100;
var l=80;
// 生成一個六瓣花型圖案的數據
for (var i=0;i<=128;i++)
{
d=w/2*(0.8+Math.sin(18*i*dig)/5)*1.2;
t=d*(0.5+Math.sin(6*i*dig)/2);
x[i]=t*Math.cos(i*dig);
y[i]=t*Math.sin(i*dig);
}
// 進行一重環形變換
for (n=1;n<=8;n++)
for (var i=0;i<=128;i++)
{
px=(2*n-1)/2*w;
x1=px+x[i];
y1=w/2+y[i];
th=2*Math.PI*(w*8-x1)/(w*8);
x2=(l+y1)*Math.cos(th)+400;
y2=(l+y1)*Math.sin(th)+250;
if (i==0)
{
context.moveTo(x2,y2);
bx=x2; by=y2;
}
else
context.lineTo(x2,y2);
}
context.lineTo(bx,by);
context.closePath();
context.stroke();
context.fill();
}
function draw3(id,k)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,800,500);
context.fillStyle="yellow";
context.strokeStyle="red";
context.lineWidth=2;
context.beginPath();
var dig=Math.PI/64;
w=200/k; l=0;
var x=new Array();
var y=new Array();
// 生成一個六瓣花型圖案的數據
for (var i=0;i<=128;i++)
{
d=w/2*(0.8+Math.sin(18*i*dig)/5)*1.2;
t=d*(0.5+Math.sin(6*i*dig)/2);
x[i]=t*Math.cos(i*dig);
y[i]=t*Math.sin(i*dig);
}
// 進行多重環形變換
for (m=1;m<=k;m++)
for (n=1;n<=8;n++)
for (var i=0;i<=128;i++)
{
px=(2*n-1)/2*w;
py=(2*m-1)/2*w;
x1=px+x[i];
y1=py-y[i];
th=2*Math.PI*(w*8-x1)/(w*8);
x2=(l+y1)*Math.cos(th)+400;
y2=(l+y1)*Math.sin(th)+250;
if (i==0)
{
context.moveTo(x2,y2);
bx=x2; by=y2;
}
else
context.lineTo(x2,y2);
}
context.lineTo(bx,by);
context.closePath();
context.stroke();
context.fill();
}
</script>
</head>
<body>
<button onClick="draw1('myCanvas');">基本圖案</button>
<button onClick="draw2('myCanvas');">環形變換</button>
<button onClick="draw3('myCanvas',2);">二重環形變換</button>
<button onClick="draw3('myCanvas',3);">三重環形變換</button>
<br/><br/>
<canvas id="myCanvas" width="800" height="500">您的瀏覽器不支持canvas!</canvas>
</body>
</html>
將上述HTML代碼保存到一個html文本文件中,再在瀏覽器中打開包含這段HTML代碼的html文件,能夠看到在瀏覽器窗口中,出現「基本圖案」、「環形變換」、「二重環形變換」、「三重環形變換」這四個按鈕,單擊「基本圖案」按鈕,繪製出如圖4所示的基本圖案,單擊「環形變換」,繪製出如圖5所示的環形變換圖案,單擊「二重環形變換」,繪製出如圖6所示的二重環形變換圖案,單擊「三重環形變換」,繪製出如圖7所示的三重環形變換圖案。
圖5 環形變換圖案
圖6 二重環形變換圖案
圖7 三重環形變換圖案
下面咱們將上面的例子進行擴充,提供多種基本圖案的選擇,選擇好基本圖案後,進行環形變換。編寫的HTML文件內容以下。
<!DOCTYPE html>
<head>
<title>可選擇圖案的環形變換</title>
<script type="text/javascript">
// 定義保存基本圖案數據的二維數組
var x=new Array(10);
var y=new Array(10);
for (var i=0;i<10;i++)
{
x[i]=new Array(129);
y[i]=new Array(129);
}
var sele=0;
function initGraph()
{
var dig=Math.PI/64;
var w=100;
// 生成一個六瓣花型圖案的數據
for (var i=0;i<=128;i++)
{
d=10*Math.sin(8*(i*dig+Math.PI/16));
x[0][i]=d*Math.cos(i*dig)+30*Math.cos(i*dig)*Math.cos(i*dig)*Math.cos(i*dig);
y[0][i]=d*Math.sin(i*dig)+30*Math.sin(i*dig)*Math.sin(i*dig)*Math.sin(i*dig);
}
// 生成一個六瓣花型圖案的數據
for (var i=0;i<=128;i++)
{
d=w/2*(0.8+Math.sin(18*i*dig)/5)*1.2;
t=d*(0.5+Math.sin(6*i*dig)/2);
x[1][i]=t*Math.cos(i*dig);
y[1][i]=t*Math.sin(i*dig);
}
// 生成一個六瓣花型圖案的數據
for (var i=0;i<=128;i++)
{
d=35*Math.sqrt(Math.abs(Math.cos(3*i*dig)));
t=d+10*Math.sqrt(Math.abs(Math.cos(9*i*dig)));
x[2][i]=t*Math.cos(i*dig)*1.2;
y[2][i]=t*Math.sin(i*dig);
}
}
initGraph();
function seleShape()
{
sele=document.frm.shape.selectedIndex-1;
drawBase('myCanvas');
}
function drawBase(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,800,500);
context.fillStyle="yellow";
context.strokeStyle="red";
context.lineWidth=1;
context.beginPath();
var dig=Math.PI/64;
var w=100;
// 在水平一行中繪製8個基本花型圖案
for (n=1;n<=8;n++)
{
px=(2*n-1)/2*w;
for (i=0;i<=128;i++)
{
x1=px+x[sele][i];
y1=w/2-y[sele][i];
if (i==0)
{
context.moveTo(x1,y1);
bx=x1; by=y1;
}
else
context.lineTo(x1,y1);
}
}
context.lineTo(bx,by);
context.closePath();
context.stroke();
context.fill();
}
function drawRound(id,k)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,800,500);
context.fillStyle="yellow";
context.strokeStyle="red";
context.lineWidth=2;
context.beginPath();
var dig=Math.PI/64;
w=80; l=10;
// 進行多重環形變換
for (m=1;m<=k;m++)
for (n=1;n<=10;n++)
for (var i=0;i<=128;i++)
{
px=(2*n-1)/2*w;
py=(2*m-1)/2*w;
x1=px+x[sele][i];
y1=py-y[sele][i];
th=2*Math.PI*(w*10-x1)/(w*10);
x2=(l+y1)*Math.cos(th)+400;
y2=(l+y1)*Math.sin(th)+250;
if (i==0)
{
context.moveTo(x2,y2);
bx=x2; by=y2;
}
else
context.lineTo(x2,y2);
}
context.lineTo(bx,by);
context.closePath();
context.stroke();
context.fill();
}
</script>
</head>
<body>
<form name="frm">基本圖案選擇:
<select name="shape" onchange="seleShape();">
<option value="圖案1">--請選擇--</option>
<option value="圖案1">圖案1</option>
<option value="圖案2">圖案2</option>
<option value="圖案3">圖案3</option>
</select>
</form>
<button onClick="drawRound('myCanvas',1);">環形變換</button>
<button onClick="drawRound('myCanvas',2);">二重環形變換</button>
<button onClick="drawRound('myCanvas',3);">三重環形變換</button>
<br/><br/>
<canvas id="myCanvas" width="800" height="500">您的瀏覽器不支持canvas!</canvas>
</body>
</html>
將上述HTML代碼保存到一個html文本文件中,再在瀏覽器中打開包含這段HTML代碼的html文件,能夠看到在瀏覽器窗口中,出現「基本圖案選擇」下拉列表框,提供三種基本圖案的選擇,還有「環形變換」、「二重環形變換」、「三重環形變換」這三個命令按鈕。選定「基本圖案」後,單擊某個按鈕,繪製出基本圖案的相應環形變換圖案。整個演示過程錄屏後展現如圖8所示。
圖8 可選擇圖案的環形變換