用于沿着球体找到不与具有特定半径的其他球体相交的点的算法

时间:2014-08-21 17:52:52

标签: c++ algorithm lua cartesian-coordinates

在3D笛卡尔空间中,我在半径为240(主球体)的XYZ处有一个球体,在该球体内有许多其他半径为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 -- 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()

2 个答案:

答案 0 :(得分:0)

最简单的方法可能是generate points at random on the boundary of the main spheretest them for intersections with the excluded balls。邻近结构(例如,kd树)将有助于渐近地进行交叉测试,但对于33个对象而言似乎不值得。计算Voronoi diagram也可能是一种解决方案,但球体上圆形有界区域的Voronoi图表将是一个不寻常的设置,可能需要相当数量的新的复杂代码。

答案 1 :(得分:0)

  1. 创建主球面的地图

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

    • 如果主要球体位于(0,0,0)半径R
    • 然后在P (x,y,z)处的球体,半径为r
    • 如果
    • 则与主球相交
    • if ((|P|<=R+r)&&(|P|>=R-r))
    • 在那种情况下计算纬度,经度来自P(见球面坐标系)
    • 将其重新映射到a,b从弧度到na,nb尺寸
    • 并将地图[a] [b](加上其周围的半径r)标记为相交
  3. 在测试完所有球体之后,您在表面上有非交叉区域的地图