How to properly visualize octree?
Closed this issue · 5 comments
Hi, thanks for your code. Is there a tool to 'visualize' the octree data?
Attached is some code to write the octree structure to a tikz figure.
import sys
import numpy as np
import matplotlib.pyplot as plt
import time
sys.path.append('../../code/common/build')
import pyoctree_cpu
def tikz_cube(f, x0,y0,z0, x1,y1,z1, fmt_str):
f.write('\\draw[%s] (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- cycle;\n' % (fmt_str, x0,y0,z0, x0,y1,z0, x1,y1,z0, x1,y0,z0))
f.write('\\draw[%s] (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- cycle;\n' % (fmt_str, x0,y0,z0, x0,y0,z1, x0,y1,z1, x0,y1,z0))
f.write('\\draw[%s] (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- cycle;\n' % (fmt_str, x0,y1,z0, x1,y1,z0, x1,y1,z1, x0,y1,z1))
f.write('\\draw[%s] (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- cycle;\n' % (fmt_str, x0,y0,z0, x1,y0,z0, x1,y0,z1, x0,y0,z1))
f.write('\\draw[%s] (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- cycle;\n' % (fmt_str, x0,y0,z1, x0,y1,z1, x1,y1,z1, x1,y0,z1))
f.write('\\draw[%s] (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- (%d,%d,%d) -- cycle;\n' % (fmt_str, x1,y0,z0, x1,y0,z1, x1,y1,z1, x1,y1,z0))
def tikz_grid_solid(f, grid, vis_grid_idx=None, color_from_data=False):
n_blocks = grid.num_blocks() if vis_grid_idx is None else 1
f.write("\\documentclass{minimal}\n")
f.write("\\usepackage{xcolor}\n")
f.write("\\usepackage{tikz,tikz-3dplot}\n")
f.write("\\begin{document}\n")
f.write("\\tdplotsetmaincoords{50}{130}\n")
f.write("\\begin{tikzpicture}[scale=0.5, tdplot_main_coords]\n")
for (leaf, grid_idx, bit_idx, gd,gh,gw, bd,bh,bw, level) in pyoctree_cpu.leaf_iterator(grid, leafs_only=False):
if color_from_data:
if leaf:
grid_data = grid.get_grid_data()
data_idx = grid.data_idx(grid_idx, bit_idx)
color = [grid_data[data_idx + 0], grid_data[data_idx + 1], grid_data[data_idx + 2]]
else:
color = [0,0,0]
else:
cm = plt.cm.get_cmap('viridis')
color = cm(grid_idx * 1.0 / n_blocks)
color = [int(255*color[0]), int(255*color[1]), int(255*color[2])]
if vis_grid_idx is not None and vis_grid_idx != grid_idx:
continue
x = gw * 8 + bw
y = gh * 8 + bh
z = gd * 8 + bd
width = 2**(3 - level)
x0 = x
y0 = y
z0 = z
x1 = x + width
y1 = y + width
z1 = z + width
if leaf or level == 0:
color_str = 'color_%d' % grid_idx
f.write('\\definecolor{%s}{RGB}{%d,%d,%d}\n' % (color_str, color[0], color[1], color[2]))
if leaf:
tikz_cube(f, x0,y0,z0, x1,y1,z1, 'very thin, gray, fill=%s,fill opacity=1.0' % (color_str))
else:
tikz_cube(f, x0,y0,z0, x1,y1,z1, 'very thick,black')
f.write("\\end{tikzpicture}\n")
f.write("\\end{document}\n")
def tikz_grid_wireframe(f, grid, vis_grid_idx=None, color_from_data=False):
n_blocks = grid.num_blocks() if vis_grid_idx is None else 1
f.write("\\documentclass{minimal}\n")
f.write("\\usepackage{xcolor}\n")
f.write("\\usepackage{tikz,tikz-3dplot}\n")
f.write("\\begin{document}\n")
f.write("\\tdplotsetmaincoords{50}{130}\n")
f.write("\\begin{tikzpicture}[scale=0.5, tdplot_main_coords]\n")
for (leaf, grid_idx, bit_idx, gd,gh,gw, bd,bh,bw, level) in pyoctree_cpu.leaf_iterator(grid, leafs_only=False):
if color_from_data:
if leaf:
grid_data = grid.get_grid_data()
data_idx = grid.data_idx(grid_idx, bit_idx)
color = [grid_data[data_idx + 0], grid_data[data_idx + 1], grid_data[data_idx + 2]]
else:
color = [0,0,0]
else:
cm = plt.cm.get_cmap('viridis')
color = cm(grid_idx * 1.0 / n_blocks)
color = [int(255*color[0]), int(255*color[1]), int(255*color[2])]
if vis_grid_idx is not None and vis_grid_idx != grid_idx:
continue
x = gw * 8 + bw
y = gh * 8 + bh
z = gd * 8 + bd
width = 2**(3 - level)
x0 = x
y0 = y
z0 = z
x1 = x + width
y1 = y + width
z1 = z + width
if leaf:
color_str = 'color_%d' % grid_idx
f.write('\\definecolor{%s}{RGB}{%d,%d,%d}\n' % (color_str, color[0], color[1], color[2]))
tikz_cube(f, x0,y0,z0, x1,y1,z1, 'very thin, %s' % (color_str))
f.write("\\end{tikzpicture}\n")
f.write("\\end{document}\n")
off_path = 'airplane_0710.off'
factor = 2
depth, height, width = 8 * factor, 8 * factor, 8 * factor
R = np.eye(3, dtype=np.float32)
grid = pyoctree_cpu.Octree.create_from_off(off_path, depth, height, width, R, pack=False, n_threads=6)
f = open('out_solid.tex', 'w')
tikz_grid_solid(f, grid)
f.close()
f = open('out_wireframe.tex', 'w')
tikz_grid_wireframe(f, grid)
f.close()
Hi, Thanks for your reply. import pyoctnet and import pyoctree_cpu which is correct? In the example code create_data.py I found import pyoctnet and pyoctnet.Octree.create_from_off. But I can't import pyoctree_cpu. Did you update the code? And I didn't find '../../code/common/build' in the current GitHub repository.
I have successfully built cpu version of core and create and can import pyoctnet but cannot import pyoctree_cpu
sys.path.append('../../code/common/build')
should point to the path, where you did build the Python extension. And replace pyoctree_cpu
with pyoctnet
.
Thanks!
Can I ask what the n_threads argument in the create functions means? I am doing medical applications and I create octree from a 512512128 dense volume, the resulting octree is very big(more than 2 Gb). I am wondering whether there are some arguments to control the size of the octree. What should I do if I want the octree be smaller? I also tried to create octree using a very fine mesh(from a CT scan), the octree is still very large. I noticed there are depth, height and width arguments. Will setting these arguments smaller help?
Is there other codes to save the visualization of octree to other formats? The generated tikz figure( .tex) sometimes is too big for overleaf to render(I use medical data)... It would be more convenient to be able to visualize it directly... It would be great if there's some documentation about the usage of the functions.