sig*_*lor 2 javascript math html5 canvas
我想构建一个嵌套正方形的圆圈,如下所示:

目前,我正在使用JavaScript/HTML5画布进行编程.这是我的代码:
<html>
<head>
<title>Circle of squares</title>
<script type="text/javascript">
var r = 150, u = 20, nests = 200; //radius in pixels, circumference in squares, nests in squares
var w = r; //any number != 0
function getNewW()
{
if(u < 3)
alert("Error: u < 3 (" + u + " < 3)!");
var tangents = new Array(new Array(0, w/2), new Array(Math.sin((1/u*360)*(Math.PI/180))*(w/2), -Math.cos((1/u*360)*(Math.PI/180))*(w/2)));
var sta = new Array(new Array(r, 0), new Array(Math.cos((1/u*360)*(Math.PI/180))*r, Math.sin((1/u*360)*(Math.PI/180))*r));
var end = new Array(new Array(sta[0][0]+tangents[0][0], sta[0][1]+tangents[0][1]), new Array(sta[1][0]+tangents[1][0], sta[1][1]+tangents[1][1]));
var pts = new Array(sta[0], end[0], sta[1], end[1]);
var intersect = new Array(((pts[0][0]*pts[1][1]-pts[0][1]*pts[1][0])*(pts[2][0]-pts[3][0]) - (pts[0][0]-pts[1][0])*(pts[2][0]*pts[3][1]-pts[2][1]*pts[3][0])) / ((pts[0][0]-pts[1][0])*(pts[2][1]-pts[3][1]) - (pts[0][1]-pts[1][1])*(pts[2][0]-pts[3][0])), ((pts[0][0]*pts[1][1]-pts[0][1]*pts[1][0])*(pts[2][1]-pts[3][1]) - (pts[0][1]-pts[1][1])*(pts[2][0]*pts[3][1]-pts[2][1]*pts[3][0])) / ((pts[0][0]-pts[1][0])*(pts[2][1]-pts[3][1]) - (pts[0][1]-pts[1][1])*(pts[2][0]-pts[3][0]))); //Formula from http://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
//distTo0 should be equal to distTo1
var distTo0 = Math.sqrt(Math.pow(sta[0][0]-intersect[0], 2) + Math.pow(sta[0][1]-intersect[1], 2));
var distTo1 = Math.sqrt(Math.pow(sta[1][0]-intersect[0], 2) + Math.pow(sta[1][1]-intersect[1], 2));
if(Math.round(distTo0*100)/100 != Math.round(distTo1*100)/100)
alert("Error: distTo0 != distTo1 (" + distTo0 + " != " + distTo1 + ")!");
return distTo0*2;
}
function start()
{
var canvas = document.getElementById("outputCanvas");
canvas.setAttribute("width", 600);
canvas.setAttribute("height", 600);
if(canvas.getContext)
{
var ctx = canvas.getContext("2d");
ctx.translate(300, 300);
w = getNewW();
for(var i=0; i<u; i++)
{
ctx.rotate((1/u*360)*(Math.PI/180));
ctx.fillRect(r, -w/2, w, w);
}
for(var j=1; j<nests; j++)
{
var oldr = r;
var temp1 = 1/(10*j+1);
while(r+w > oldr) //This is the while-loop that makes the program slow
{
r -= temp1;
w = getNewW();
}
if(r < 0) //When the radius gets smaller than 0, the center is reached -> no new squares have to be drawn
break;
var temp2 = (1/u*360)*(Math.PI/180);
for(var i=0; i<u; i++)
{
ctx.rotate(temp2);
ctx.fillRect(r, -w/2, w, w);
}
}
}
}
</script>
</head>
<body id="main" onload="start()">
<canvas style="border:1px #000000 solid;" width="0" height="0" id="outputCanvas">Canvas not supported...</canvas>
<div id="info"> </div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
但由于我没有解决方案的公式,我使用while循环来越来越接近解决方案(直到它因为浮动不准确而达到零),这就是为什么它很慢.那么,可以使用什么公式来计算(思考)圆内的下一个正方形的宽度,如果有必要,可以在其他地方优化代码?
圆附近,那里的方块是足够小的中心,可以近似的一侧(长度W¯¯由弧长) -也就是说,一个多久ü个内圆的是,如果你画了它作为一个实际圈子.这只是在弧度的角度(2 π/ù)倍穿过正方形的内角那张的圆的半径.由于您r的代码有所不同,我将在单个时刻r2调用特定的半径值; 这使得弧长:
w_approx = (2 * Math.PI / u) * r2
Run Code Online (Sandbox Code Playgroud)
但是对于你图片中的大多数方块而言,它与w的实际值之间的差异太大了; 如果你使用它作为边长,你将得到重叠的正方形.幸运的是,我们也可以直接计算w的真实值; 它只需要一点三角学.
如果从正方形的内角到圆的中心绘制线条,那么这两条线加上正方形的内侧形成一个三角形.我们知道我们刚刚画出的这两条线有多长; 它们等于内半径.我们不知道第三边有多长-这就是价值W¯¯我们要找的-但我们知道与它相对的角度.这三条信息足以计算w.
这是一张图片来展示我在说什么:

在圆,标记的中心的角度α在图片(阿尔法),仅仅是一个ü第一个完整的圆,其值为2的π/ù弧度(或360/ù度,但三角函数所有期望弧度) :
alpha = 2 * Math.PI / u
Run Code Online (Sandbox Code Playgroud)
三角形的另外两个角度是相等的(它们必须是,因为它们是相等的长度相等的边),因此它们都被标记为β.由于三角形的三个角总是加起来为π弧度(或180°),我们可以计算β ; 它等于(π - α)/ 2弧度:
beta = (Math.PI - alpha)/2
Run Code Online (Sandbox Code Playgroud)
根据正弦定律,如果你将任何三角形任何一边的长度除以与该边相反的角度的正弦,无论你选择哪三边,结果都是一样的.这告诉我们,w ^/罪 α必须是一样的R2/罪 β.解决w的等式得到了我们:
w = r2 * Math.sin(alpha) / Math.sin(beta)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
488 次 |
| 最近记录: |