我正在用Python编写一些代码(目前为止只是为了好玩),它将在3d空间中的每个点上存储一些数据。我基本上是在一个存储任意对象的3d矩阵对象之后,这些对象允许我做一些高级选择,例如:
在上述所有内容中,我需要最终得到某种输出,这些输出会给我空间中的原始位置,以及存储在该点的数据。
显然numpy可以做我想要的,但它似乎高度优化了科学计算,并且弄清楚如何获得我想要的数据到目前为止还没有找到我。
有没有更好的选择,还是我应该回到笨拙的墙上敲我的头? :)
编辑:更多信息前三个答案让我意识到我应该包括:我不担心性能,这纯粹是一个概念验证,我更喜欢干净的代码以获得良好的性能。我还将获得给定3d空间中每个点的数据,所以我猜一个备用矩阵是不好的?答案 0 :(得分:4)
这是另一种常见方法
class Point( object ):
def __init__( self, x, y, z, data ):
self.x, self.y, self.z = x, y, z
self.data = data
def distFrom( self, x, y, z )
return math.sqrt( (self.x-x)**2 + (self.y-y)**2 + (self.z-z)**2 )
database = [ Point(x,y,z,data), Point(x,y,z,data), ... ]
让我们来看看你的用例。
得到x = 1,y = 2,z = 3的点。
[ p for p in database if (p.x, p.y, p.z) == ( 1, 2, 3 ) ]
获取y = 2的所有点。
[ p for p in database if p.y == 2 ]
将所有点置于位置x = 1,y = 2,z = 3的3个单位内。
[ p for p in database if p.distFrom( 1, 2, 3 ) <= 3.0 ]
获取所有点point.getType()==“Foo”
[ p for p in database if type(p.data) == Foo ]
答案 1 :(得分:3)
答案 2 :(得分:1)
numpy的一个优点是它非常快,
例如计算8000x8000邻接矩阵的pagerank需要几毫秒。即使numpy.ndarray
只接受数字,您也可以将数字/ id-object映射存储在外部哈希表中,即字典(再次是高度优化的数据结构)。
切片就像在python中列表切片一样简单:
>>> from numpy import arange
>>> the_matrix = arange(64).reshape(4, 4, 4)
>>> print the_matrix[0][1][2]
6
>>> print the_matrix[0][1]
[4 5 6 7]
>>> print the_matrix[0]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
如果围绕某个核心矩阵和id-object-mapping散列包裹一些所需的函数(距离),则可以在短时间内运行应用程序。
祝你好运!答案 3 :(得分:0)
您可以使用numpy中的切片执行前2个查询:
a = numpy.zeros((4, 4, 4))
a[1, 2, 3] # The point at x=1,y=2,z=3
a[:, 2, :] # All points where y=2
对于第三个,如果你的意思是“在半径3的范围内得到所有点并且以x = 1,y = 2,z = 3为中心”,你将必须编写一个自定义函数来做到这一点;如果你想要一个立方体,你可以进行切片,例如:
a[1:3, 1:3, 1:3] # The 2x2x2 array sliced from the center of 'a'
对于第四个查询,如果存储在数组中的唯一数据是单元格类型,则可以将其编码为整数:
FOO = 1
BAR = 2
a = numpy.zeros((4, 4, 4), dtype="i")
a[1, 2, 3] = FOO
a[3, 2, 1] = BAR
def filter(a, type_code):
coords = []
for z in range(4):
for y in range(4):
for x in range(4):
if a[x, y, z] == type_code:
coords.append((x, y, z))
return coords
filter(a, FOO) # => [(1, 2, 3)]
numpy看起来像是做你想要的好工具,因为数组在内存中会更小,可以在C中轻松访问(甚至更好,cython!)并且扩展切片语法将避免你编写代码。
答案 4 :(得分:0)
这是一种可行的方法。
每个点都是一个4元组(x,y,z,数据),您的数据库如下所示:
database = [ (x,y,z,data), (x,y,z,data), ... ]
让我们来看看你的用例。
得到x = 1,y = 2,z = 3的点。
[ (x,y,z,data) for x,y,z,data in database if (x,y,z) == (1,2,3) ]
获取y = 2的所有点。
[ (x,y,z,data) for x,y,z,data in database if y == 2 ]
将所有点置于位置x = 1,y = 2,z = 3的3个单位内。
[ (x,y,z,data) for x,y,z,data in database if math.sqrt((x-1)**2+(y-2)**2+(z-3)**2)<=3.0 ]
获取所有点point.getType()==“Foo”
[ (x,y,z,data) for x,y,z,data in database if type(data) == Foo ]
答案 5 :(得分:0)
When to use Binary Space Partitioning, Quadtree, Octree?
3d array imo毫无价值。特别是如果你的世界充满活力。您应该在BSP,四叉树或八叉树之间做出决定。 BSP会做得很好。由于你的世界是3d,你在分割bsp时需要平面,而不是线。
干杯!
修改
我也会为每一点提供数据 在给定的3d空间中,所以我猜一个 备用矩阵不好?
我想如果总是知道你的数据集有多大并且它永远不会改变,那就没关系,即如果有更多的点被添加到它,那么它又会超出界限。在这种情况下,您必须调整3d数组的大小。
答案 6 :(得分:0)
如果你想要一个标准库的相对简单的解决方案,那么使用带有x,y,z元组作为键的字典是另一种解决方案。
import math
#use indexing to get point at (1,2,3): points[(1,2,3)]
get_points(points, x=None, y=None, x=None):
"""returns dict of all points with given x,y and/or z values. Call using keywords (eg get_points(points, x=3)"""
filteredPoints = points.items()
if x:
filteredPoints = [p for p in filteredPoints if p[0][0] == x]
if y:
filteredPoints = [p for p in filteredPoints if p[0][1] == y]
if z:
filteredPoints = [p for p in filteredPoints if p[0][0] == x]
return dict(filteredPoints)
get_point_with_type(points, type_):
"""returns dict of points with point.getType() == type_"""
filteredPoints = points.items()
return dict((position,data) for position,data in points.iterItems() if data.getType == type_)
get_points_in_radius(points,x,y,z,r):
"""Returns a dict of points within radius r of point (x,y,z)"""
def get_dist(x1,y1,z1,x2,y2,z3):
return math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2))
return dict((position,data) for position,data in points.iterItems() if get_dist(x,y,z, *position) <= r))
由于python引用,你可以改变返回词典中的“点”,并且原始点也会改变(我认为)。
答案 7 :(得分:-1)
这取决于系统的精确配置,但是从您给出的示例中使用的是整数和离散点,因此考虑Sparse Matrix数据结构可能是合适的。