计算封闭世界中的光强度

时间:2017-02-09 19:45:46

标签: algorithm math

我正在构建一个模拟,其中世界由许多正方形组成。还有一些被称为“太阳”的物体,它们照亮了方块,并在每一步都更新了它们的“接收强度”。

例如:
enter image description here

在此图像中,正方形中心之间的距离为32个单位,每个正方形的接收强度(或 R.I。)使用以下公式计算:

  

R.I。 = 100 /(光源和方形之间的距离)^ 2

用通用(和可怕的)编程语言编写,计算R.I.的函数可能如下所示:

(define (calc-RI sq-x sq-y sn-x sn-y)
    (return (/ 100 
               (+ (square (- sq-x sn-x)) 
                  (square (- sq-y sn-y))
               )
            )
    )
)

...并且,为了容纳多个太阳,每个太阳的R.I.将被单独计算并且为每个方格加在一起。这一切都很好,直到我觉得需要在这个模拟中引入一个翘曲机制:在世界边缘“移动”的对象将从另一个“重新进入”世界像游戏中的小行星一样 这不仅需要应用于模拟中的其他对象,还需要轻巧 enter image description here 那么,新函数应该用于计算每个方格的R.I.? (假设该函数采用一个正方形和一个太阳的 x y 坐标,以及宽度高度

1 个答案:

答案 0 :(得分:0)

您可以通过想象网格被原始网格的副本包围来解决这个问题,每个包裹一个层。对于原始网格中的每个正方形,计算落在每个相应正方形上的光强度,并对结果求和。

enter image description here

在上图中,黑色网格代表世界,蓝色网格代表世界网格的副本。要在绿色方块上找到一个包裹的光强度,请将在每个蓝色方块计算的简单强度添加到为绿色方块计算的简单强度。要计算另一个包装,请添加另一层副本。

这是一些实现此功能的Lua代码。星形表示在表格中:

stars = { { x=x1, y=y1 }, { x=x2, y=y2 },... }

在此实现中,包含星形的正方形的强度为-1。这可以改变,使得包含恒星的正方形像任何其他正方形一样累积强度。要使用这些功能,请定义stars表,然后使用light_universe()(此处网格为正方形),grid_sizesquare_size表调用stars ,以及wraps期望的数量。将wraps设置为零,nil,或者只是省略此参数,以获得没有包装的简单强度计算。函数light_universe()返回一个表,其中包含世界网格每个方格的强度。您可以使用show_intensities()返回的表格和表格的light_universe()调用grid_size来查看结果。请注意,世界网格的左上角有坐标(1,1)。

calculate_intensity()函数首先计算网格副本字段的field_size。这是图中蓝色网格的大小,是grid_size的奇数倍,例如,对于1个包裹,field_size是3.接下来,当前{{1}的世界坐标转换为字段坐标starstar_x(相对于图中蓝色网格的坐标)。然后迭代对应于star_yx的字段内的位置。这些是图表蓝色方块的位置。第一个位置位于场的左上角网格中,其场地坐标等于感兴趣的正方形的世界坐标。对于每个位置,计算强度并将其添加到运行总计中,该值在迭代完成时返回。

y

这是一个显示强度而没有换行的交互,对应于您问题中的示例。

-- Intensity calculation with wraps
-- wraps = nil or wraps = 0 for simple calculation
function calculate_intensity(star, x, y, grid_size, square_size, wraps)
   wraps = wraps or 0
   local field_size = grid_size * (2 * wraps + 1)      -- odd number of grids
   local star_x = star.x + wraps * grid_size           -- cdts of star in field
   local star_y = star.y + wraps * grid_size
   local intensity = 0
   -- x and y are cdts wrt world grid, but also wrt first grid in field
   for field_y = y, field_size, grid_size do
      for field_x = x, field_size, grid_size do
         local dx = square_size * (star_x - field_x)
         local dy = square_size * (star_y - field_y)         
         local dist_sq = dx * dx + dy * dy
         intensity = intensity + 100 / dist_sq
      end
   end
   return intensity
end

function light_universe(grid_size, square_size, stars, wraps)
   wraps = wraps or 0
   local grid_intensities = {}
   for i, star in ipairs(stars) do
      for y = 1, grid_size do
         grid_intensities[y] = grid_intensities[y] or {}
         for x = 1, grid_size do
            if x == star.x and y == star.y then
               grid_intensities[y][x] = -1
            elseif grid_intensities[y][x] ~= -1 then
               grid_intensities[y][x] = (grid_intensities[y][x] or 0) +
                  calculate_intensity(star, x, y, grid_size, square_size, wraps)
            end
         end
      end
   end
   return grid_intensities
end

function show_intensities(grid, grid_size)
   for y = 1, grid_size do
      for x = 1, grid_size do
         local intensity = grid[y][x]
         local fmt
         if intensity ~= -1 then
            fmt = (string.format("%10.5f", intensity))
         else
            fmt = string.format("%-10s", "   Star")
         end
         io.write(fmt)
      end
      print()
   end
end

以下是一个包​​装的相同情况:

> stars = { { x=1, y=1 } }
> light_grid = light_universe(3, 32, stars, 0)
> show_intensities(light_grid, 3)
   Star      0.09766   0.02441
   0.09766   0.04883   0.01953
   0.02441   0.01953   0.01221

有两个包装:

> light_grid = light_universe(3, 32, stars, 1)
> show_intensities(light_grid, 3)
   Star      0.17054   0.16628
   0.17054   0.12440   0.12023
   0.16628   0.12023   0.11630

这是一个7X7网格,有两颗星,一个包裹:

> light_grid = light_universe(3, 32, stars, 2)
> show_intensities(light_grid, 3)
   Star      0.20497   0.20347
   0.20497   0.15960   0.15811
   0.20347   0.15811   0.15664