add extra materials related to lewiner mc algorithm

This commit is contained in:
Almar Klein
2016-04-20 02:41:09 +02:00
parent 19740b0ff9
commit b954ba5024
4 changed files with 3863 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+175
View File
@@ -0,0 +1,175 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2012, Almar Klein
""" Create lookup tables for the marching cubes algorithm, by parsing
the file "LookUpTable.h". This prints a text to the stdout wich
can then be copied to luts.py.
The luts are tuples of shape and base64 encoded bytes.
"""
import numpy as np
import sys
import base64
# Get base64 encode/decode functions
PY3 = sys.version_info[0] == 3
if PY3:
base64encode = base64.encodebytes
base64decode = base64.decodebytes
else:
base64encode = base64.encodestring
base64decode = base64.decodestring
def create_luts(fname):
# Get the lines in the C header file
text = open(fname,'rb').read().decode('utf-8')
lines1 = [line.rstrip() for line in text.splitlines()]
# Init lines for Python
lines2 = []
# Get classic table
more_lines, ii = get_table(lines1, 'static const char casesClassic', 0)
lines2.extend(more_lines)
# Get cases table
more_lines, ii = get_table(lines1, 'static const char cases', 0)
lines2.extend(more_lines)
# Get tiling tables
ii = 0
for casenr in range(99):
# Get table
more_lines, ii = get_table(lines1, 'static const char tiling', ii+1)
if ii < 0:
break
else:
lines2.extend(more_lines)
# Get test tables
ii = 0
for casenr in range(99):
# Get table
more_lines, ii = get_table(lines1, 'static const char test', ii+1)
if ii < 0:
break
else:
lines2.extend(more_lines)
# Get subconfig tables
ii = 0
for casenr in range(99):
# Get table
more_lines, ii = get_table(lines1, 'static const char subconfig', ii+1)
if ii < 0:
break
else:
lines2.extend(more_lines)
return '\n'.join(lines2)
def get_table(lines1, needle, i):
# Try to find the start
ii = search_line(lines1, needle, i)
if ii < 0:
return [], -1
# Init result
lines2 = []
# Get size and name
front, dummu, back = lines1[ii].partition('[')
name = front.split(' ')[-1].upper()
size = int(back.split(']',1)[0])
cdes = lines1[ii].rstrip(' {=')
# Write name
lines2.append('%s = np.array([' % name)
# Get elements
for i in range(ii+1, ii+1+9999999):
line1 = lines1[i]
front, dummy, back = line1.partition('*/')
if not back:
front, back = back, front
line2 = ' '
line2 += back.strip().replace('{', '[').replace('}',']').replace(';','')
line2 += front.replace('/*',' #').rstrip()
lines2.append(line2)
if line1.endswith('};'):
break
# Close and return
lines2.append(" , 'int8')")
lines2.append('')
#return lines2, ii+size
# Execute code and get array as base64 text
code = '\n'.join(lines2)
code = code.split('=',1)[1]
array = eval(code)
array64 = base64encode(array.tostring()).decode('utf-8')
# Reverse: bytes = base64decode(text.encode('utf-8'))
text = '%s = %s, """\n%s"""' % (name, str(array.shape), array64)
# Build actual lines
lines2 = []
#lines2.append( '# %s -> %s %s' % (cdes, str(array.dtype), str(array.shape)) )
lines2.append( '#' + cdes)
lines2.append(text)
lines2.append('')
return lines2, ii+size
def search_line(lines, refline, start=0):
for i, line in enumerate(lines[start:]):
if line.startswith(refline):
return i + start
return -1
def getLutNames(prefix):
aa = []
for a in dir(luts):
if a.startswith(prefix): aa.append(a)
def sortkey(x):
fullnr = x.split(prefix)[1]
nr, us, subnr = fullnr.partition('_')
if len(nr) == 1:
nr = '0'+nr
return nr + us + subnr
return [a for a in sorted(aa, key=sortkey)]
if __name__ == '__main__':
import os
fname = os.path.join(os.getcwd(), 'LookUpTable.h')
if True:
with open(os.path.join(os.getcwd(), 'mcluts.py'), 'w') as f:
f.write('# -*- coding: utf-8 -*-\n')
f.write('# Copyright (C) 2012, Almar Klein\n# Copyright (C) 2002, Thomas Lewiner\n\n')
f.write('# This file was auto-generated from LookUpTable.h by createluts.py.\n\n')
f.write(create_luts(fname))
else:
for prefix in ['TILING', 'TEST']:
tmp = ['luts.'+a for a in getLutNames(prefix)]
print(', '.join(tmp))
print('')
for name in getLutNames(prefix):
print('self.%s = Lut(%s)' % (name, name))
print('')
for name in getLutNames(prefix):
print('cdef Lut %s' % name)
print('')
print('')
+64
View File
@@ -0,0 +1,64 @@
"""
Script to show the results of the two marching cubes algorithms on different
data.
"""
import time
import numpy as np
import visvis as vv
from skimage.measure import marching_cubes, marching_cubes_lewiner
# Create test volume
SELECT = 1
if SELECT == 1:
# Medical data
vol = vv.volread('stent')
isovalue = 800
elif SELECT == 2:
# Blocky data
vol = vv.aVolume(20, 128) # Different every time
isovalue = 0.2
elif SELECT == 3:
# Generate two donuts
n = 48
a, b = 2.5/n, -1.25
isovalue = 0.0
#
vol = np.empty((n,n,n), 'float32')
for iz in range(vol.shape[0]):
for iy in range(vol.shape[1]):
for ix in range(vol.shape[2]):
z, y, x = float(iz)*a+b, float(iy)*a+b, float(ix)*a+b
vol[iz,iy,ix] = ( (
(8*x)**2 + (8*y-2)**2 + (8*z)**2 + 16 - 1.85*1.85 ) * ( (8*x)**2 +
(8*y-2)**2 + (8*z)**2 + 16 - 1.85*1.85 ) - 64 * ( (8*x)**2 + (8*y-2)**2 )
) * ( ( (8*x)**2 + ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2 + 16 - 1.85*1.85 )
* ( (8*x)**2 + ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2 + 16 - 1.85*1.85 ) -
64 * ( ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2
) ) + 1025
# Uncommenting the line below will yield different results for classic MC
#vol = -vol
# Get surface meshes
t0 = time.time()
vertices1, faces1, *_ = marching_cubes_lewiner(vol, isovalue, use_classic=False)
print('finding surface lewiner took %1.0f ms' % (1000*(time.time()-t0)) )
t0 = time.time()
vertices2, faces2, *_ = marching_cubes(vol, isovalue)
print('finding surface classic took %1.0f ms' % (1000*(time.time()-t0)) )
# Show
vv.figure(1); vv.clf()
a1 = vv.subplot(121); vv.mesh(np.fliplr(vertices1), faces1)
a2 = vv.subplot(122); vv.mesh(np.fliplr(vertices2), faces2)
a1.camera = a2.camera
vv.use().Run()