【问题标题】:How to calculate and place circles on an rect area?如何计算并在矩形区域上放置圆圈?
【发布时间】:2014-09-16 23:54:42
【问题描述】:

我正在尝试在画布区域上绘制一些图表。我的问题是...

我要画 1-4 个(或更多)圆圈。画布大小为 500 x 400 像素。我现在如何计算每个圆的最大半径以将所有内容放在此画布上并获取每个圆的位置(中心 x/y)?那么每个圆圈可以最佳地放置在彼此之间有一定边距的区域上吗?

这里有一些示例屏幕向您展示我的意思...

非常感谢!

【问题讨论】:

    标签: javascript jquery math canvas jcanvas


    【解决方案1】:

    您所询问的Knapsack problem 很难解决。在您的情况下,最好的方法是使用给定的表,例如 http://www.packomania.com。如果可以,请将自己限制在一个正方形内。

    【讨论】:

    • 感谢您的快速回答。我认为这很复杂。也许上面的新图片更有帮助。我想把它们像桌子一样。
    • 问题与knapstack无关。是包装问题! en.wikipedia.org/wiki/Packing_problem。 OP 查询的问题实例很简单。
    • 我回答了最初的问题。只有在编辑后才变得如此琐碎。
    【解决方案2】:

    计算可以使用的最大半径

        var numberOfSections = 4;
        var width = 500;
        var height = 400;
        var R = Math.sqrt((width * height) / numberOfSections) / 2
    
        var MX = Math.round(width / (R * 2)); // max amount of squares that can fit on the width
        var MY = Math.round(height / (R * 2)); // max amount of squares that can fit on the height
    
    var skipLast = 0;
    var numOfCalculatedCircles = MX*MY;
    if(numOfCalculatedCircles != numberOfSections) {
    
        if(numOfCalculatedCircles < numberOfSections) {
            console.log('numOfCalculatedCircles',numOfCalculatedCircles);
            MX = MX + Math.ceil((numberOfSections - numOfCalculatedCircles)/MY);
            if(MX*MY != numberOfSections) {
                skipLast = Math.abs(MX*MY - numberOfSections);
            }
        } else {
            skipLast = numOfCalculatedCircles - numberOfSections;;
        }
    
        console.log('MX*MY',MX*MY);
    }
    // recalculate the radius for X
    if (R * 2 * MX > width) {
        R = (width/2) / MX;
    }
    
    // recalculate the radius for Y
    if (R * 2 * MY > height) {
        R = (height/2) / MY
    }
    

    计算 X 和 Y 的边距:

        var circlesWidth = R * 2 * MX;
        var circlesHeight = R * 2 * MY;
    
        var marginX = 0;
        var marginY = 0;
        if (circlesWidth < width) {
            marginX = (width - circlesWidth) / 2
        }
        if (circlesHeight < height) {
            marginY = (height - circlesHeight) / 2
        }
    

    之后你可以计算中心:

    var RY = marginY + R;
    var radiusPadding = 10;
    
    for (var i = 0; i < MY; i++) {
        var RX = marginX + R;
        for (var j = 0; j < MX; j++) {
            if(i === MY - 1) {
              if(j === MX - skipLast) {
                break;
              }
            }
            canvas.drawArc({
                fromCenter: true,
                strokeStyle: 'red',
                strokeWidth: 1,
                start: 0,
                end: 360,
                radius: R - radiusPadding,
                x: RX,
                y: RY
            });
    
            RX += 2 * R;
        }
    
        RY += 2 * R;
    }
    

    希望这会有所帮助。

    更新:它仍然不完整,但它可能适用于这个特定的示例:http://jsfiddle.net/dhM96/4/

    【讨论】:

    • 看起来很有趣,但我不知道如何修改它。我已经尝试过,但它绘制了 6 个半径很大且位置错误的圆圈。 var numberOfSections = data.length, // 当前:4 R = Math.sqrt((cWidth * cHeight) / numberOfSections) / 2, center = []; for( var x = R, y = R; ; x += 2 * R) { if(x >= cWidth) { x = R; y += R; if( y >= cHeight ) 中断; } canvas.drawArc({ fromCenter: true, strokeStyle: strokeStyle, strokeWidth: strokeWidth, start: 0, end: 360, radius: R, x: x, y: y }); }
    • @HR123 抱歉,这个答案不完整,回答你的问题比我想象的要复杂。我创建了一个 jsfiddle,您可以将其用作参考:jsfiddle.net/hn7u7/3。如果这对你有用,我会更新我的答案。
    • 非常感谢!!!这很难……你做得很好。但是有一个小问题...如果您将 numberOfSections 更改为 2 或 5 或类似的东西不再起作用...我尝试将数字四舍五入,但您的代码/数学对我来说很难...希望您能再次帮助我完成最后一步。非常感谢
    【解决方案3】:

    您没有提供足够的展示位置限制。

    无论如何,假设沿矩形边缘有F 像素的空闲空间和圆圈之间的f,则X 上的最大半径为Rx = (Width - 2 F - (Nx-1) f) / 2YR y = (Height - 2F - (Ny-1) f) / 2。 (Nx 水平圆圈,Ny 垂直圆圈。)取两者中最小的。

    中心将位于(F + (2 Rx + f) Ix + Rx, F + (2 Ry + f) Iy + Ry)0 &lt;= Ix &lt; Nx0 &lt;= Iy &lt; Ny

    【讨论】:

      猜你喜欢
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多