Select Git revision
python_context_parser.cc
generate_map_iso_spec.py 6.97 KiB
#------------------------------------------------------------------------------
# This file is part of the OpenStructure project <www.openstructure.org>
#
# Copyright (C) 2008-2010 by the OpenStructure authors
#
# 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 3.0 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
#------------------------------------------------------------------------------
#
# Author: Ansgar Philippsen
#
# automatically generate iso-contouring marching cube specs
#
import math
# cube definition
# corners:
# 5 6
# -------
# /. /|
# / . / |
# 1 ------ 2 |
# | ....|..|
# | .4 | / 7
# |. |/
# ------
# 0 3
# vertices:
# ---9---
# 5. 6|
# / 8 / |
# ---1-- 10
# | ..11|..|
# 0 4 2 7
# |. |/
# --3---
# faces 2
# .
# -------
# / /|
# / 1 / |
# ------ .|.. 5
#4..| | |
# | 0 | /
# | |/.
# ------ 3
corner_coord=[[0,0,0],[0,1,0],[1,1,0],[1,0,0],
[0,0,1],[0,1,1],[1,1,1],[1,0,1]]
edge_corner=[[0,1],[1,2],[2,3],[3,0],
[0,4],[1,5],[2,6],[3,7],
[4,5],[5,6],[6,7],[4,7]]
face_edges=[[0,1,2,3],[1,5,9,6],[9,8,11,10],
[11,7,3,4],[4,8,5,0],[7,2,6,10]]
header_code="""
// automatically generated by generate_map_iso_spec.py
// do not edit directly
#include "map_iso_gen.hh"
namespace ost { namespace gfx { namespace map_iso {
template<int N>
void AddLinesAndFaces(IndexedVertexArray& va, // vertex array
unsigned int vertex_id[12] // this list of vertex ids
);
"""
isocube_header_code="""
template<>
void AddLinesAndFaces<%d>(IndexedVertexArray& va,unsigned int vertex_id[12] )
{
"""
isocube_addline_code=""" va.AddLine(vertex_id[%d],vertex_id[%d]);
"""
isocube_addface_code=""" va.AddTriN(vertex_id[%d],vertex_id[%d],vertex_id[%d]);
"""
isocube_debug_code="""
#ifdef MAP_ISO_DEBUG
if(vertex_id[%d]==0) std::cerr << \"ISO_DEBUG: \" << %d << \" \" << %d << std::endl;
if(vertex_id[%d]==0) std::cerr << \"ISO_DEBUG: \" << %d << \" \" << %d << std::endl;
if(vertex_id[%d]==0) std::cerr << \"ISO_DEBUG: \" << %d << \" \" << %d << std::endl;
#endif
"""
isocube_footer_code="}\n"
flist_header_code="""
void GenerateLFList(AddLFList& lfl)
{
lfl.clear();
"""
flist_code=" lfl.push_back(AddLinesAndFaces<%d>);\n"
flist_footer_code="""
}
"""
footer_code="""
}}} // ns
"""
def vadd(v1,v2):
return [v1[0]+v2[0],
v1[1]+v2[1],
v1[2]+v2[2]]
def vsub(v1,v2):
return [v1[0]-v2[0],
v1[1]-v2[1],
v1[2]-v2[2]]
def vmul(s,v1):
return [v1[0]*s,
v1[1]*s,
v1[2]*s]
def vdot(v1,v2):
return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]
def vcross(v1,v2):
return [v1[1]*v2[2]-v2[1]*v1[2],
v1[2]*v2[0]-v2[2]*v1[0],
v1[0]*v2[1]-v2[0]*v1[1]]
def vnorm(v1):
len2=v1[0]*v1[0]+v1[1]*v1[1]+v1[2]*v1[2]
return vmul(1.0/math.sqrt(len2),v1)
def work(spec_file,pattern):
corner_bit=[0,0,0,0,0,0,0,0]
for i in range(8):
if pattern & (1<<i):
corner_bit[i]=1
edge_bit=[0,0,0,0,0,0,0,0,0,0,0,0]
edge_list=[]
for i in range(12):
if corner_bit[edge_corner[i][0]] != corner_bit[edge_corner[i][1]]:
edge_bit[i]=1
edge_list.append(i)
spec_file.write(isocube_header_code%pattern)
# first the lines
edge_pairs=[]
for e1 in edge_list:
for e2 in edge_list:
if e1>e2:
for f in face_edges:
if e1 in f and e2 in f:
# line across a face
edge_pairs.append([e1,e2])
spec_file.write(isocube_addline_code%(e1,e2))
# find line-loop(s)
while len(edge_pairs)>0:
edge_loop=[]
edge_loop.extend(edge_pairs[0])
edge_pairs.remove(edge_pairs[0])
closed=False
while not closed:
for ep in edge_pairs:
if ep[0]==edge_loop[len(edge_loop)-1]:
if ep[1]==edge_loop[0]:
closed=True
else:
edge_loop.append(ep[1])
edge_pairs.remove(ep)
break
elif ep[1]==edge_loop[len(edge_loop)-1]:
if ep[0]==edge_loop[0]:
closed=True
else:
edge_loop.append(ep[0])
edge_pairs.remove(ep)
break
# find correct orientation
# assemble dir0 from middle of edge and the higher value corner
edge_id0 = edge_loop[0]
v00 = edge_corner[edge_id0][0]
v01 = edge_corner[edge_id0][1]
e0_pos = vmul(0.5,vadd(corner_coord[v00],corner_coord[v01]))
e1_pos=[0,0,0]
if corner_bit[v00]==1:
e1_pos=corner_coord[v00]
else:
e1_pos=corner_coord[v01]
dir0 = vnorm(vsub(e1_pos,e0_pos))
# assemble dir1 from the cross product of the lines of the
# edge_loop
edge_id1 = edge_loop[1]
v10 = edge_corner[edge_id1][0]
v11 = edge_corner[edge_id1][1]
edge_id2 = edge_loop[2]
v20 = edge_corner[edge_id2][0]
v21 = edge_corner[edge_id2][1]
e1_pos = vmul(0.5,vadd(corner_coord[v10],corner_coord[v11]))
e2_pos = vmul(0.5,vadd(corner_coord[v20],corner_coord[v21]))
e10 = vsub(e0_pos,e1_pos)
e12 = vsub(e2_pos,e1_pos)
dir1 = vnorm(vcross(e10,e12))
# this is the actual orientation check
if vdot(dir0,dir1)<0.0:
edge_loop.reverse()
# dump code to file
for i in range(len(edge_loop)-2):
spec_file.write(isocube_addface_code%(edge_loop[0],edge_loop[i+2],edge_loop[i+1]))
spec_file.write(isocube_debug_code%(edge_loop[0],edge_loop[0],pattern,
edge_loop[i+2],edge_loop[i+2],pattern,
edge_loop[i+1],edge_loop[i+1],pattern))
spec_file.write(isocube_footer_code)
spec_file=file("map_iso_spec.hh","w")
spec_file.write(header_code)
for i in range(256):
work(spec_file,i)
spec_file.write(flist_header_code)
for i in range(256):
spec_file.write(flist_code%i)
spec_file.write(flist_footer_code)
spec_file.write(footer_code)