Interactive 3D content in LaTeX

Movie15 Package

The movie15 package can be used to include interactive 3D content (in U3D format) within a LaTeX document. When opening the resulting PDF with Adobe Acrobat, the content can be visualized interactively.

Code snippet to include example.u3d

\usepackage[3D]{movie15}
...
\includemovie[
poster,
toolbar,
label=example.u3d,
text=(example.u3d),
3Daac=60.000000, 3Droll=0.000000,
3Dc2c=0.613500 -7.545900 0.855200,
3Droo=7.618947,
3Dcoo=0.613470 0.649878 -0.855214,
3Dlights=CAD,
]
{\linewidth}
{\linewidth}
{example.u3d}

Conversion of X3D to U3D

The free software MeshLab can import X3D and export U3D file formats.

X3D example: Elastic modulus cube

To visualize the directional elastic modulus of cubic crystals based on the C11, C12, and C44 values of the elastic stiffness tensor, use below script

#!/usr/bin/env python
'''Create a unitsphere recursively by subdividing all triangles in an octahedron recursively.

A unitsphere has a radius of 1, which also means that all points in this sphere
have an absolute value of 1.
Another feature of an unitsphere is that the normals of this sphere are exactly the same as the vertices.

This recursive method will avoid the common problem of the polar singularity,
produced by 2D parameterization methods.

If you wish a sphere with a radius other than 1, simply multiply every single
value in the vertex array with this new radius
(although this will break the "vertex array equal to normal array" property)
'''
import sys,numpy as np

octahedron_vertices = np.array( [
[ 1.0, 0.0, 0.0], # 0
[-1.0, 0.0, 0.0], # 1
[ 0.0, 1.0, 0.0], # 2
[ 0.0,-1.0, 0.0], # 3
[ 0.0, 0.0, 1.0], # 4
[ 0.0, 0.0,-1.0] # 5
] )
octahedron_triangles = np.array( [
[ 0, 2, 4 ],
[ 2, 1, 4 ],
[ 1, 3, 4 ],
[ 3, 0, 4 ],
[ 0, 5, 2 ],
[ 2, 5, 1 ],
[ 1, 5, 3 ],
[ 3, 5, 0 ],
] )

def E_hkl(stiffness,arr): # stiffness = (c11,c12,c44)
S11 = (stiffness[0]+stiffness[1])/(stiffness[0]*stiffness[0]+stiffness[0]*stiffness[1]-2.0*stiffness[1]*stiffness[1])
S12 = ( -stiffness[1])/(stiffness[0]*stiffness[0]+stiffness[0]*stiffness[1]-2.0*stiffness[1]*stiffness[1])
S44 = 1.0/stiffness[2]

invE = S11-(S11-S12-0.5*S44)* (1.0 - \
(arr[:,0]**4+arr[:,1]**4+arr[:,2]**4) \
/#------------------------------------------------
(arr[:,0]**2+arr[:,1]**2+arr[:,2]**2)**2)

arr[:,0] /= invE
arr[:,1] /= invE
arr[:,2] /= invE
return arr

def normalize_v3(arr):
''' Normalize a np array of 3 component vectors shape=(n,3) '''
lens = np.sqrt( arr[:,0]**2 + arr[:,1]**2 + arr[:,2]**2 )
arr[:,0] /= lens
arr[:,1] /= lens
arr[:,2] /= lens
return arr

def divide_all( vertices, triangles, stiffness=[1,0.5,0.25] ):
#new_triangles = []
new_triangle_count = len( triangles ) * 4
# Subdivide each triangle in the old approximation and normalize
# the new points thus generated to lie on the surface of the unit
# sphere.
# Each input triangle with vertices labeled [0,1,2] as shown
# below will be turned into four new triangles:
#
# Make new points
# a = (0+1)/2
# b = (1+2)/2
# c = (2+0)/2
# 2
# /\ Normalize a, b, c
# / \
# c/____\ b Construct new triangles
# /\ /\ t1 [0,a,c]
# / \ / \ t2 [c,b,2]
# /____\/____\ t3 [a,1,b]
# 0 a 1 t4 [a,b,c]
v0 = vertices[ triangles[:,0] ] # all first points (N,3)
v1 = vertices[ triangles[:,1] ] # all second points
v2 = vertices[ triangles[:,2] ] # all third points
a = ( v0+v1 ) * 0.5 # all points between first and second points
b = ( v1+v2 ) * 0.5 # all points between second and third points
c = ( v2+v0 ) * 0.5 # all points between third and first points
normalize_v3( a ) # project onto unit sphere
normalize_v3( b )
normalize_v3( c )
E_hkl( stiffness, a ) # E along a
E_hkl( stiffness, b ) # E along b
E_hkl( stiffness, c ) # E along c

#Stack the triangles together.
vertices = np.hstack( (v0,a,c, c,b,v2, a,v1,b, a,b,c,) ).reshape(-1,3)
#Now our vertices are duplicated, and thus our triangle structure are unnecessary.
return vertices, np.arange( len(vertices) ).reshape( (-1,3) )

def create_E_sphere( stiffness=[1,0.5,0.25], recursion_level=2 ):
vertex_array, index_array = E_hkl( stiffness,octahedron_vertices), octahedron_triangles
for i in range( recursion_level - 1 ):
vertex_array, index_array = divide_all(vertex_array, index_array, stiffness)
return vertex_array, index_array

def create_unit_sphere( recursion_level=2 ):
vertex_array, index_array = octahedron_vertices, octahedron_triangles
for i in range( recursion_level - 1 ):
vertex_array, index_array = divide_all(vertex_array, index_array)
return vertex_array, index_array

def vertex_array_only_unit_sphere( recursion_level=2 ):
vertex_array, index_array = create_unit_sphere(recursion_level)
if recursion_level > 1:
return vertex_array.reshape( (-1) )
else:
return vertex_array[index_array].reshape( (-1) )

(vertices,indices) = create_E_sphere(map(float,sys.argv[2:5]),int(sys.argv[1]))

print '''<!--?xml version="1.0" encoding="UTF-8"?-->

'''

print ''
print ''
print ''

print '''

'''
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s