对齐圆内的矩形
Align rectangles inside circle
我有一个圆,我需要用矩形填充这个圆。是这样的:
是否有一些算法或建议从哪里开始?
我使用 fabric.js 进行绘图。这是playground。但是,问题可能更多是关于数学的。我认为应该有一些公式,我希望。
我现在使用 "close enough":用半径减去矩形长度,然后将结果乘以 2π。那是内圈。现在将其除以矩形宽度(并向下舍入)以获得矩形的数量。将 360° 除以得到绘制它们的角度。
我已经更新了您提供的 JSBin 文件。代码我已经注释了很多细节,这里就不多解释了。
var canvas = new fabric.Canvas(document.querySelector('#my-canvas'));
var circleRadius = 250;
var boxHeight = 30;
var boxWidth = 150;
function createCircleAndBoxes(radius, boxHeight, boxWidth) {
var circle = new fabric.Circle({
radius: circleRadius,
fill: '#f3aa25',
stroke: '#333'
});
canvas.add(circle);
// Calculates the center of the circle
circle.left = (canvas.width - circle.width) / 2;
circle.top = (canvas.height - circle.width) / 2;
// The inner lines of the boxes make a circle
// Calculate the circumference of this circle.
// By dividing the height of the box by the calculated circumference
// We can get the number of boxes needed
var innerCircumference = 2 * Math.PI * (circleRadius - boxWidth);
var roughBoxCount = Math.floor(innerCircumference / boxHeight);
// Each box is placed exactly at the center of the circle
var calculatedTop = circle.top + (circle.height / 2) - 1;
var calculatedLeft = circle.left + (circle.width / 2) + 1;
// By changing the origin to a negative point away from the box,
// the box is translated. Also, all rotatopms are done from this point
// The trick however is that, the origin point is calculated
// as a percentage of the height and width. For instance, 0.5 means center
// Therefore, we align the origin point with the circle center and
// calculate the offset as a percentage
var calculatedOriginX = (boxWidth - circleRadius) / boxWidth;
var calculatedOriginY = (boxHeight / 2) / boxHeight;
// Since we have the number of boxes needed, we can calculate
// what's the angle each box needs to be rotated
var calculatedAngle = 360 / roughBoxCount;
// Combine all these, and you got your requirement
for(var i = 0; i<roughBoxCount; i++) {
var rect = new fabric.Rect({
angle: calculatedAngle * i,
top: calculatedTop,
left: calculatedLeft,
centeredRotation: false,
originX: calculatedOriginX,
originY: calculatedOriginY,
width: boxWidth,
height: boxHeight,
fill: '#e3e3e3',
stroke: '#333'
});
canvas.add(rect);
}
}
createCircleAndBoxes(circleRadius, boxHeight, boxWidth);
了解平移、旋转和中心点计算,这是此类开发的关键。我的方法与 'user348173' 上面的答案略有不同。但我想,两者都值得一试
我有一个圆,我需要用矩形填充这个圆。是这样的:
是否有一些算法或建议从哪里开始? 我使用 fabric.js 进行绘图。这是playground。但是,问题可能更多是关于数学的。我认为应该有一些公式,我希望。
我现在使用 "close enough":用半径减去矩形长度,然后将结果乘以 2π。那是内圈。现在将其除以矩形宽度(并向下舍入)以获得矩形的数量。将 360° 除以得到绘制它们的角度。
我已经更新了您提供的 JSBin 文件。代码我已经注释了很多细节,这里就不多解释了。
var canvas = new fabric.Canvas(document.querySelector('#my-canvas'));
var circleRadius = 250;
var boxHeight = 30;
var boxWidth = 150;
function createCircleAndBoxes(radius, boxHeight, boxWidth) {
var circle = new fabric.Circle({
radius: circleRadius,
fill: '#f3aa25',
stroke: '#333'
});
canvas.add(circle);
// Calculates the center of the circle
circle.left = (canvas.width - circle.width) / 2;
circle.top = (canvas.height - circle.width) / 2;
// The inner lines of the boxes make a circle
// Calculate the circumference of this circle.
// By dividing the height of the box by the calculated circumference
// We can get the number of boxes needed
var innerCircumference = 2 * Math.PI * (circleRadius - boxWidth);
var roughBoxCount = Math.floor(innerCircumference / boxHeight);
// Each box is placed exactly at the center of the circle
var calculatedTop = circle.top + (circle.height / 2) - 1;
var calculatedLeft = circle.left + (circle.width / 2) + 1;
// By changing the origin to a negative point away from the box,
// the box is translated. Also, all rotatopms are done from this point
// The trick however is that, the origin point is calculated
// as a percentage of the height and width. For instance, 0.5 means center
// Therefore, we align the origin point with the circle center and
// calculate the offset as a percentage
var calculatedOriginX = (boxWidth - circleRadius) / boxWidth;
var calculatedOriginY = (boxHeight / 2) / boxHeight;
// Since we have the number of boxes needed, we can calculate
// what's the angle each box needs to be rotated
var calculatedAngle = 360 / roughBoxCount;
// Combine all these, and you got your requirement
for(var i = 0; i<roughBoxCount; i++) {
var rect = new fabric.Rect({
angle: calculatedAngle * i,
top: calculatedTop,
left: calculatedLeft,
centeredRotation: false,
originX: calculatedOriginX,
originY: calculatedOriginY,
width: boxWidth,
height: boxHeight,
fill: '#e3e3e3',
stroke: '#333'
});
canvas.add(rect);
}
}
createCircleAndBoxes(circleRadius, boxHeight, boxWidth);
了解平移、旋转和中心点计算,这是此类开发的关键。我的方法与 'user348173' 上面的答案略有不同。但我想,两者都值得一试