diff options
Diffstat (limited to 'render_povray/df3_library.py')
-rwxr-xr-x | render_povray/df3_library.py | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/render_povray/df3_library.py b/render_povray/df3_library.py new file mode 100755 index 00000000..f802fb2d --- /dev/null +++ b/render_povray/df3_library.py @@ -0,0 +1,403 @@ +################################################################################ +# +# df3.py +# +# Copyright (C) 2005 Mike Kost <contact@povray.tashcorp.net> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# +################################################################################ +# +# Creation functions +# __init__(x=1, y=1, z=1) : default constructor +# clone(indf3) : make this df3 look like indf3 +# +# Info functions +# sizeX(): returns X dimension +# sizeY(): returns Y dimension +# sizeZ(): returns Z dimension +# +# Scalar functions +# mult(): +# add(): +# max(): returns highest voxel value in df3 +# min(): returns lowest voxel value in df3 +# +# Vector functions +# +# Import/Export functions +# exportDF3(): +# importDF3(): +# +################################################################################ + +import struct +import os +import stat +import array +import sys + +# -+-+-+- Start df3 Class -+-+-+- + + +class df3: + __version__ = '0.2' + + __arraytype__ = 'f' + + __struct4byte__ = '>I' + __struct2byte__ = '>H' + __struct2byte3__ = '>HHH' + __struct1byte__ = '>B' + __array4byte__ = 'I' + __array2byte__ = 'H' + __array1byte__ = 'B' + + def __init__(self, x=1, y=1, z=1): + self.maxX = x + self.maxY = y + self.maxZ = z + self.voxel = self.__create__(x, y, z) + + def clone(self, indf3): + self.voxel = array.array(self.__arraytype__) + for i in range(indf3.sizeX() * indf3.sizeY() * indf3.sizeZ()): + self.voxel[i] = indf3.voxel[i] + return self + + #### Info Functions + + def sizeX(self): + return self.maxX + + def sizeY(self): + return self.maxY + + def sizeZ(self): + return self.maxZ + + def size(self): + tmp = [] + tmp.append(self.sizeX()) + tmp.append(self.sizeY()) + tmp.append(self.sizeZ()) + return tmp + + #### Voxel Access Functions + + def get(self, x, y, z): + return self.voxel[self.__voxa__(x, y, z)] + + def getB(self, x, y, z): + if x > self.sizeX() or x < 0: + return 0 + if y > self.sizeX() or y < 0: + return 0 + if z > self.sizeX() or z < 0: + return 0 + + return self.voxel[self.__voxa__(x, y, z)] + + def set(self, x, y, z, val): + self.voxel[self.__voxa__(x, y, z)] = val + + def setB(self, x, y, z, val): + if x > self.sizeX() or x < 0: + return + if y > self.sizeX() or y < 0: + return + if z > self.sizeX() or z < 0: + return + + self.voxel[self.__voxa__(x, y, z)] = val + + #### Scalar Functions + + def mult(self, val): + for i in range(self.sizeX() * self.sizeY() * self.sizeZ()): + self.voxel[i] = self.voxel[i] * val + + return self + + def add(self, val): + for i in range(self.sizeX() * self.sizeY() * self.sizeZ()): + self.voxel[i] = self.voxel[i] + val + + return self + + def max(self): + tmp = self.voxel[0] + + for i in range(self.sizeX() * self.sizeY() * self.sizeZ()): + if self.voxel[i] > tmp: + tmp = self.voxel[i] + + return tmp + + def min(self): + tmp = self.voxel[0] + + for i in range(self.sizeX() * self.sizeY() * self.sizeZ()): + if self.voxel[i] < tmp: + tmp = self.voxel[i] + + return tmp + + #### Vector Functions + + def compare(self, indf3): + if self.__samesize__(indf3) == 0: + return 0 + + if self.voxel == indf3.voxel: + return 1 + + return 0 + + def multV(self, indf3): + if self.__samesize__(indf3) == 0: + print("Cannot multiply voxels - not same size") + return + + for i in range(self.sizeX() * self.sizeY() * self.sizeZ()): + self.voxel[i] = self.voxel[i] * indf3.voxel[i] + + return self + + def addV(self, indf3): + if self.__samesize__(indf3) == 0: + print("Cannot add voxels - not same size") + return + + for i in range(self.sizeX() * self.sizeY() * self.sizeZ()): + self.voxel[i] = self.voxel[i] + indf3.voxel[i] + + return self + + def convolveV(self, filt): + fx = filt.sizeX() + fy = filt.sizeY() + fz = filt.sizeZ() + if fx % 2 != 1: + print("Incompatible filter - must be odd number of X") + return self + if fy % 2 != 1: + print("Incompatible filter - must be odd number of Y") + return self + if fz % 2 != 1: + print("Incompatible filter - must be odd number of Z") + return self + + fdx = (fx - 1) / 2 + fdy = (fy - 1) / 2 + fdz = (fz - 1) / 2 + flen = fx * fy * fz + + newV = self.__create__(self.sizeX(), self.sizeY(), self.sizeZ()) + + for x in range(self.sizeX()): + for y in range(self.sizeY()): + for z in range(self.sizeZ()): + rip = self.__rip__(x - fdx, x + fdx, y - fdy, y + fdy, z - fdz, z + fdz) + tmp = 0.0 + for i in range(flen): + tmp += rip[i] * filt.voxel[i] + newV[self.__voxa__(x, y, z)] = tmp + + self.voxel = newV + + return self + + #### Import/Export Functions + + def exportDF3(self, file, depth=8, rescale=1): + x = self.sizeX() + y = self.sizeY() + z = self.sizeZ() + + try: + f = open(file, 'wb') + except: + print("Could not open " + file + " for write") + return + + f.write(struct.pack(self.__struct2byte3__, x, y, z)) + + tmp = self.__toInteger__(pow(2, depth) - 1, rescale) + + if depth > 16: # 32-bit + for i in range(x * y * z): + f.write(struct.pack(self.__struct4byte__, tmp[i])) + elif depth > 8: # 16-bit + for i in range(x * y * z): + f.write(struct.pack(self.__struct2byte__, tmp[i])) + else: + for i in range(x * y * z): + f.write(struct.pack(self.__struct1byte__, tmp[i])) + + def importDF3(self, file, scale=1): + try: + f = open(file, 'rb') + size = os.stat(file)[stat.ST_SIZE] + + except: + print("Could not open " + file + " for read") + return [] + + (x, y, z) = struct.unpack(self.__struct2byte3__, f.read(6)) + + self.voxel = self.__create__(x, y, z) + self.maxX = x + self.maxY = y + self.maxZ = z + + size = size - 6 + if size == x * y * z: + format = 8 + elif size == 2 * x * y * z: + format = 16 + elif size == 4 * x * y * z: + format = 32 + + if format == 32: + for i in range(x * y * z): + self.voxel[i] = float(struct.unpack(self.__struct4byte__, f.read(4))[0]) + elif format == 16: + for i in range(x * y * z): + self.voxel[i] = float(struct.unpack(self.__struct2byte__, f.read(2))[0]) + elif format == 8: + for i in range(x * y * z): + self.voxel[i] = float(struct.unpack(self.__struct1byte__, f.read(1))[0]) + + return self + + #### Local classes not intended for user use + + def __rip__(self, minX, maxX, minY, maxY, minZ, maxZ): + sizeX = maxX - minX + 1 + sizeY = maxY - minY + 1 + sizeZ = maxZ - minZ + 1 + + tmpV = self.__create__(sizeX, sizeY, sizeZ) + + for x in range(sizeX): + for y in range(sizeY): + for z in range(sizeZ): + # Check X + if (minX + x) < 0: + tmpV[(z * sizeZ + y) * sizeY + x] = 0.0 + elif (minX + x) > self.sizeX() - 1: + tmpV[(z * sizeZ + y) * sizeY + x] = 0.0 + # Check Y + elif (minY + y) < 0: + tmpV[(z * sizeZ + y) * sizeY + x] = 0.0 + elif (minY + y) > self.sizeY() - 1: + tmpV[(z * sizeZ + y) * sizeY + x] = 0.0 + # Check Z + elif (minZ + z) < 0: + tmpV[(z * sizeZ + y) * sizeY + x] = 0.0 + elif (minZ + z) > self.sizeZ() - 1: + tmpV[(z * sizeZ + y) * sizeY + x] = 0.0 + else: + tmpV[(z * sizeZ + y) * sizeY + x] = self.get(minX + x, minY + y, minZ + z) + + return tmpV + + def __samesize__(self, indf3): + if self.sizeX() != indf3.sizeX(): + return 0 + if self.sizeY() != indf3.sizeY(): + return 0 + if self.sizeZ() != indf3.sizeZ(): + return 0 + return 1 + + def __voxa__(self, x, y, z): + return (z * self.sizeY() + y) * self.sizeX() + x + + def __create__(self, x, y, z, atype='0', init=1): + if atype == '0': + tmp = self.__arraytype__ + else: + tmp = atype + + if init == 1: + if tmp in ('f', 'd'): + voxel = array.array(tmp, [0.0 for i in range(x * y * z)]) + else: + voxel = array.array(tmp, [0 for i in range(x * y * z)]) + else: + voxel = array.array(tmp) + + return voxel + + def __toInteger__(self, scale, rescale=1): + if scale < pow(2, 8): # 8-bit + tmp = self.__create__(self.sizeX(), self.sizeY(), self.sizeZ(), self.__array1byte__) + elif scale < pow(2, 16): # 16-bit + tmp = self.__create__(self.sizeX(), self.sizeY(), self.sizeZ(), self.__array2byte__) + else: # 32-bit + tmp = self.__create__(self.sizeX(), self.sizeY(), self.sizeZ(), self.__array4byte__) + + maxVal = self.max() + + print(scale) + + for i in range(self.sizeX() * self.sizeY() * self.sizeZ()): + if rescale == 1: + tmp[i] = max(0, int(round(scale * self.voxel[i] / maxVal))) + else: + tmp[i] = max(0, min(scale, int(round(self.voxel[i])))) + + return tmp + + +# -=-=-=- End df3 Class -=-=-=- +##########DEFAULT EXAMPLES +# if __name__ == '__main__': +# localX = 80 +# localY = 90 +# localZ = 100 +## Generate an output +# temp = df3(localX, localY, localZ) + +# for i in range(localX): +# for j in range(localY): +# for k in range(localZ): +# if (i >= (localX/2)): +# temp.set(i, j, k, 1.0) + +# temp.exportDF3('temp.df3', 16) +############################################################################### +## Import +# temp2 = df3().importDF3('temp.df3') +# temp2.mult(1/temp2.max()) + +## Compare +# print(temp2.size()) + +# if (temp.compare(temp2) == 0): print("DF3's Do Not Match") + +############################################################################### +# ChangeLog +# --------- +# 08/09/05: 0.20 released +# + Change internal representation to floating point +# + Rewrite import/export for speed +# + Convert from 3-d list structure to Array class for data storage +# + Add element access, scalar, and vector functions +# 07/13/05: 0.10 released +############################################################################### |