寻找沿着球体的点的算法,这些点不与具有特定半径的其他球体相交。

在 $3D$ 笛卡尔空间中,我有一个坐标为 XYZ、半径为 $240$ 的球体(主球),其内部有许多半径为 $100$ 的其他球体(其他物体)。我需要能够找到沿着边界的点,这些点没有被任何内部物体所相交。

为了简单起见,我们可以假设主球位于坐标为 $(0,0,0)$,半径为 $240$,内部有约 $33$ 个物体,每个物体在不同的坐标位置,半径均为 $100$。

大部分使用 Lua 编写,但 C/C++ 也可以。任何帮助都将得到赞赏,哪怕只是指导我如何在数学上解决问题。

编辑:使用 David Eisenstat 提供的链接和信息,这是我正在使用的代码。它“似乎”有效,但还没有完全测试。

function randomSpherePoint(x, y, z, r)
  local acos, sin, cos = math.acos, math.sin, math.cos
  local u, v = math.random(), math.random()
  local theta = 2 * PI * u
  local phi = acos(2 * v - 1)
  local px = x + (r * sin(phi) * cos(theta))
  local py = y + (r * sin(phi) * sin(theta))
  local pz = z + (r * cos(phi))
  return px, py, pz
end

function fun_bordercheck()
  local results = { }
  local bx, by, bz, radius = -9197.944, 0, 0, 240 -- 边界位置和半径

  for i = 1, 1000 do -- 随机测试 1000 个点
    local px, py, pz = randomSpherePoint(bx, by, bz, radius)
    local n = 0
    while (n < #space_objs) do
      n = n + 1
      if (xyz2range(space_objs[n].x, space_objs[n].y, space_objs[n].z, px, py, pz) <=100) then
        break -- 如果相交了,就没有必要再检查其他物体了。跳到下一个随机点
      end
      if (n == #space_objs) then -- 如果检查到列表的末尾,这将是一个可能的位置。存储它
        results[#results+1] = { x = px, y = py, z = pz }
      end
    end -- while()
  end -- for()

  if (#results < 1) then
    print("No points found.")
    return
  end
  print(string.format("BorderCheck(): Found %d results.", #results))
  for i = 1, #results do
    Note(string.format("Point %d: %.3f %.3f %.3f", i, results[i].x, results[i].y, results[i].z))
  end
end -- function()
点赞
用户2144669
用户2144669

可能最简单的方法是在主要球体的边界上随机生成点,并且测试它们是否与被排除的球体相交。接近度结构(例如,kd-tree)可以在渐近意义下帮助相交测试,但对于33个对象而言似乎不值得投入。计算Voronoi图也可能是一种解决方案,但是在球体上生成的圆形边界区域的Voronoi图是一个非常不寻常的情境,可能需要花费大量的新编织、复杂的代码。

2014-08-21 18:08:22
用户2521214
用户2521214

在主球面上创建地图

  • 例如:
  • const int na=128;
  • const int nb=256;
  • int map[na][nb];
  • 这样,map [a] [b] 是围绕 a(纬度),b(经度)的表面积。

测试所有小球是否与主球相交

  • 如果主球位于 (0,0,0),半径为 R
  • 那么位于 P(x,y,z),半径为 r 的球与主球相交
  • 如果
  • if ((|P|<=R+r)&&(|P|>=R-r))
  • 在这种情况下,根据 P 计算纬度,经度 (查看球坐标系)。
  • 从弧度重新映射到 na,nb 尺寸的 a,b
  • 并将 map [a] [b](以及其半径为 r 的周围区域)标记为相交。

对所有球进行测试后,您将获得表面上不相交区域的地图

2014-08-21 18:20:11