我正在尝试制作一堆具有内在几何属性(中心点,半径,长度等)的几何对象,以及帮助绘制它们的属性(如x,y,z坐标)三角网,弧分辨率等。)。
由于计算x,y,z坐标对于某些形状来说是一项昂贵的任务(比如带有边缘倒圆的三角形棱柱),我不希望每次更改属性时都这样做,但只有当请求坐标。即便如此,如果形状的定义没有改变,也没有必要重新计算它们。
所以我的解决方案是创建一个“哈希”,它只是定义形状“状态”的所有参数的元组。如果散列不变,则可以重新使用先前计算的坐标,否则必须重新计算坐标。所以我使用哈希作为存储形状定义的签名或指纹的方法。
我认为我的工作原理,但我想知道是否有更强大的方法可以利用__hash__
或id或其他东西来处理这个问题。这对我来说太过分了,但我愿意接受建议。
这是我对球体的实现。我正在使用Mayavi进行最后的绘图,如果你没有Mayavi,你可以跳过/忽略。
#StdLib Imports
import os
#Numpy Imports
import numpy as np
from numpy import sin, cos, pi
class Sphere(object):
"""
Class for a sphere
"""
def __init__(self, c=None, r=None, n=None):
super(Sphere, self).__init__()
#Initial defaults
self._coordinates = None
self._c = np.array([0.0, 0.0, 0.0])
self._r = 1.0
self._n = 20
self._hash = []
#Assign Inputs
if c is not None:
self._c = c
if r is not None:
self._r = r
if n is not None:
self._n = n
@property
def c(self):
return self._c
@c.setter
def c(self, val):
self._c = val
@property
def r(self):
return self._r
@r.setter
def r(self, val):
self._r = val
@property
def n(self):
return self._n
@n.setter
def n(self, val):
self._n = val
@property
def coordinates(self):
self._lazy_update()
return self._coordinates
def _lazy_update(self):
new_hash = self._get_hash()
old_hash = self._hash
if new_hash != old_hash:
self._update_coordinates()
def _get_hash(self):
return tuple(map(tuple, [self._c, [self._r, self._n]]))
def _update_coordinates(self):
c, r, n = self._c, self._r, self._n
dphi, dtheta = pi / n, pi / n
[phi, theta] = np.mgrid[0:pi + dphi*1.0:dphi,
0:2*pi + dtheta*1.0:dtheta]
x = c[0] + r * cos(phi) * sin(theta)
y = c[1] + r * sin(phi) * sin(theta)
z = c[2] + r * cos(theta)
self._coordinates = x, y, z
self._hash = self._get_hash()
if __name__ == '__main__':
from mayavi import mlab
ns = [4, 6, 8, 10, 20, 50]
sphere = Sphere()
for i, n in enumerate(ns):
sphere.c = [i*2.2, 0.0, 0.0]
sphere.n = n
mlab.mesh(*sphere.coordinates, representation='wireframe')
mlab.show()
正如所建议的,这是一个使用字典将哈希存储为密钥的版本:
#StdLib Imports
import os
#Numpy Imports
import numpy as np
from numpy import sin, cos, pi
class Sphere(object):
"""
Class for a sphere
"""
def __init__(self, c=None, r=None, n=None):
super(Sphere, self).__init__()
#Initial defaults
self._coordinates = {}
self._c = np.array([0.0, 0.0, 0.0])
self._r = 1.0
self._n = 20
#Assign Inputs
if c is not None:
self._c = c
if r is not None:
self._r = r
if n is not None:
self._n = n
@property
def c(self):
return self._c
@c.setter
def c(self, val):
self._c = val
@property
def r(self):
return self._r
@r.setter
def r(self, val):
self._r = val
@property
def n(self):
return self._n
@n.setter
def n(self, val):
self._n = val
@property
def _hash(self):
return tuple(map(tuple, [self._c, [self._r, self._n]]))
@property
def coordinates(self):
if self._hash not in self._coordinates:
self._update_coordinates()
return self._coordinates[self._hash]
def _update_coordinates(self):
c, r, n = self._c, self._r, self._n
dphi, dtheta = pi / n, pi / n
[phi, theta] = np.mgrid[0:pi + dphi*1.0:dphi,
0:2 * pi + dtheta*1.0:dtheta]
x = c[0] + r * cos(phi) * sin(theta)
y = c[1] + r * sin(phi) * sin(theta)
z = c[2] + r * cos(theta)
self._coordinates[self._hash] = x, y, z
if __name__ == '__main__':
from mayavi import mlab
ns = [4, 6, 8, 10, 20, 50]
sphere = Sphere()
for i, n in enumerate(ns):
sphere.c = [i*2.2, 0.0, 0.0]
sphere.n = n
mlab.mesh(*sphere.coordinates, representation='wireframe')
mlab.show()
答案 0 :(得分:0)
为什么不简单地留一个旗帜:
class Sphere(object):
def __init__(self, ...):
...
self._update_coordinates()
...
@c.setter
def c(self, val):
self._changed = True
self._c = val
...
def _lazy_update(self):
if self._changed:
self._update_coordinates()
def _update_coordinates(self):
...
self._changed = False