寻找沿球面不与具有特定半径的其他球面相交的点的算法

Algorithm to find points along a sphere that do not intersect with other spheres with a specific radius

本文关键字:其他 面相 算法 寻找      更新时间:2023-10-16

在三维笛卡尔空间中,我在XYZ有一个半径为240的球体(主球体),在这个球体内有许多半径为100的其他球体(其他物体)。我需要能够找到沿边界球边界的点,这些点不与它内部的任何其他物体相交。

为简单起见,我们可以说主球体位于00 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 -- Border location and radius
  for i = 1, 1000 do -- 1000 random points
    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 -- It hits, no point in checking any other objects. Skip to next random point
      end
      if (n == #space_objs) then -- We reached the end of the list. If we got this far, this is a     possible location. Store it
        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()

可能最简单的方法是在主球的边界上随机生成点,并测试它们与被排除的球的相交。接近结构(例如,kd-树)将有助于渐近交叉测试,但似乎不值得在33个对象的前景。计算Voronoi图也是一种解决方案,但是球体上圆形边界区域的Voronoi图将是一个不寻常的设置,可能需要相当数量的新的,复杂的代码。

  1. 创建主球面地图

      例如:
    • const int na=128;
    • const int nb=256;
    • int map[na][nb];
    • 所以地图[a][b]是a(纬度),b(经度)周围的表面积
  2. 测试所有小球体是否与主球体相交

    • 如果主球在(0,0,0),半径为R
    • 则以r为半径的P (x,y,z)球面
  3. if ((|P|<=R+r)&&(|P|>=R-r))
  4. 在这种情况下计算纬度,经度从P(见球坐标系)
  5. 重新映射到a,b从弧度到na,nb尺寸
  6. 和标记地图[a][b](加上其周围半径为r)相交
  7. 在所有球体测试后,您将获得表面上非相交区域的地图

相关文章: