【问题标题】:Drawing Geometrical and Mathematical Algorithm绘制几何和数学算法
【发布时间】:2014-01-21 07:40:42
【问题描述】:

我有一个特定的需求,这变成了一个有趣的数学问题。

给定一个数字 n 和固定距离 d 和点 p(x,y) 在固定宽度和高度的矩形 R(即屏幕)内。 我想在矩形内绘制 n 个正方形,最大尺寸可能(所有正方形大小相同)并且正方形不相交并且彼此分开最小距离 d(与正方形周长的距离)。

这些方格也应该与给定点 P(基本上是鼠标最后记录的位置)的距离至少为 d。

如果有解决办法,请告诉我。

解决方案应该给出正方形的大小和所有正方形的坐标。

相反的有趣问题可以是正方形的大小,可以绘制多少个这样的正方形。

【问题讨论】:

    标签: algorithm html5-canvas geometry computational-geometry


    【解决方案1】:

    简单(可能不是最优)方法:通过二分搜索找到 a 的最大值

    Floor((Width + d) / a) * Floor((Height + d) / a) >= n+1
    

    并用边(a - d)制作n个正方形的规则网格,不包括有点的地方

    【讨论】:

      【解决方案2】:

      你要求的,你得到它

      我有一个小提琴 here,它可能会进行近乎最佳的平铺。
      不过,这太丑了。

      这让我想起了我的一些客户坚持涉足详细规格而不是停留在功能要求级别:)。

      算法的核心在这里:

      compute: function ()
      {
          function try_size (x1, x2, y1, y2, w, h, y)
          {
              var d = Math.sqrt((this.w+this.h)/this.n);
              var delta = 10*d;
              var n = 0;
              while ((delta > 1e-12) || (n < this.n))
              {
                  var res = {};
                  if (y < (d/2-this.d))
                  {
                      res.x1 = res.x2 = res.y1 = 0;
                      res.y2 = Math.floor ((h-y-this.d)/d);
                      res.c1 = true;
                  }
                  else if (y > (h-d+2*this.d))
                  {
                      res.x1 = res.x2 = res.y2 = 0;
                      res.y1 = Math.floor ((y-this.d)/d);
                      res.c2 = true;
                  }
                  else
                  {
                      res.y1 = Math.floor((y1-d/2)/d);
                      res.y2 = Math.floor((y2-d/2)/d);
                      res.x1 = Math.floor ((x1-this.d/2)/d);
                      res.x2 = Math.floor ((x2-this.d/2)/d);
                  }
                  res.w = Math.floor ((w+this.d)/d);
                  n = res.x1+res.x2+res.w*(res.y1+res.y2);
                    
                  d += n > this.n ? delta : -delta;
                  if (delta > 1e-12) delta /=2;
              }
              res.d = d;
              res.s = d-2*this.d;
              return res;
          }
      

      这个想法是定期平铺矩形,除了中心点周围的带。此带的水平和垂直变体被尝试保留最大的正方形大小。

      我猜一个最佳解决方案不会使乐队围绕中心点居中,但鉴于结果看起来很糟糕,我认为这不值得:)

      better-looking but less optimal solution:

      (只是一个概念证明;一些边缘情况处理不当)。

          compute: function ()
          {
              var d = Math.sqrt((this.w+this.h)/this.n);
              var delta = 100*d;
              while ((delta > 1e-12) || (res.n < this.n))
              {
                  var res = {};
                  res.x = Math.floor ((this.w-this.x%d)/d);
                  res.y = Math.floor ((this.h-this.y%d)/d);
                  res.n = res.x * res.y;
                    
                  d += res.n > this.n ? delta : -delta;
                  if (delta > 1e-12) delta /=2;
              }
              res.d = d;
              res.s = d-2*this.d;
              res.a = 0;
              this.res = res;
          },
      

      移动参考点仍然会导致正方形大小摆动。
      不过,作为图形效果可能会很有趣。

      【讨论】:

        猜你喜欢
        • 2019-05-20
        • 2014-09-18
        • 2017-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-09
        • 1970-01-01
        相关资源
        最近更新 更多