tag:support.nodebox.net,2012-11-01:/discussions/show-your-work/81-toroidal-polyhedron-code-based-on-torus-by-mark-meyer
NodeBox: Discussion
2016-08-11T12:04:57Z
tag:support.nodebox.net,2012-11-01:Comment/35614025
2014-12-25T23:09:05Z
2014-12-25T23:09:06Z
Toroidal Polyhedron code based on "Torus" by Mark Meyer
<div><p>The following replacement in the appropriate section for the
code above can ease vertex manipulation:</p>
<hr>
<h1><a name=
"n-defines-how-many-vertices-we-find-the-number-will-be-n-2-" href=
"#n-defines-how-many-vertices-we-find-the-number-will-be-n-2-"
class="anchor" id=
"n-defines-how-many-vertices-we-find-the-number-will-be-n-2-"></a>n
defines how many vertices we find: the number will be n^2.</h1>
<h1><a name="large-values-of-n-can-take-a-while-to-render-" href=
"#large-values-of-n-can-take-a-while-to-render-" class="anchor" id=
"large-values-of-n-can-take-a-while-to-render-"></a>Large values of
n can take a while to render!</h1>
<h1><a name="utilize-only-integer-numbers-for-n-w-q-" href=
"#utilize-only-integer-numbers-for-n-w-q-" class="anchor" id=
"utilize-only-integer-numbers-for-n-w-q-"></a>Utilize only integer
numbers for n, w, q.</h1>
<p>n = 10<br>
w = float(n)/10 # number of sides along the axis of revolution<br>
q = float(n)/4 # number of sides around the poloidal axis</p>
<h1><a name="-torus-equation-" href="#-torus-equation-" class=
"anchor"></a>--- TORUS EQUATION
--------------------------------------------------------</h1>
<h1><a name="define-parametric-equations-for-each-axis-" href=
"#define-parametric-equations-for-each-axis-" class="anchor" id=
"define-parametric-equations-for-each-axis-"></a>Define parametric
equations for each axis.</h1>
<h1><a name="although-we-define-an-z-coordinate-" href=
"#although-we-define-an-z-coordinate-" class="anchor" id=
"although-we-define-an-z-coordinate-"></a>Although we define an z
coordinate,</h1>
<h1><a name="it-is-only-used-in-transformations-and-shading-" href=
"#it-is-only-used-in-transformations-and-shading-" class="anchor"
id="it-is-only-used-in-transformations-and-shading-"></a>it is only
used in transformations and shading;</h1>
<h1><a name="it-is-not-used-in-the-drawing" href=
"#it-is-not-used-in-the-drawing" class="anchor" id=
"it-is-not-used-in-the-drawing"></a>it is not used in the
drawing</h1>
<h1><a name=
"-although-it-could-be-if-you-wanted-to-add-perspective-" href=
"#-although-it-could-be-if-you-wanted-to-add-perspective-" class=
"anchor"></a>(although it could be if you wanted to add
perspective).</h1>
<p>r1 = 165<br>
r2 = 55<br>
def x(u, v): return (r1 + r2 * cos(v)) * cos(u)<br>
def y(u, v): return (r1 + r2 * cos(v)) * sin(u)<br>
def z(u, v): return r2 * sin(v)</p>
<p>def fit_to_domain(u, v):<br>
u = w * u/n * pi*2 v = q * v/n * pi*2 return u, v</p></div>
Dr. Ozan Yarman
tag:support.nodebox.net,2012-11-01:Comment/35614025
2014-12-26T17:38:43Z
2014-12-26T17:38:44Z
Toroidal Polyhedron code based on "Torus" by Mark Meyer
<div><p>After correcting a glitch in the rotational matrix, re-aligning
the torus to face directly at RUN, and assigning all three (x, y,
z) axes to appropriate rotational manipulations, I copy/paste the
updated code below. Notice also, the vertex input section is more
obvious now.</p>
<p>Enjoy!<br>
Assoc. Prof. Dr. Ozan Yarman<br>
<a href="http://www.ozanyarman.com">www.ozanyarman.com</a></p>
<hr>
<h1><a class="anchor" name=
"-quot-toroidal-polyhedron-quot-by-dr-ozan-yarman-http-www-ozanyarman-com-"
href=
"#-quot-toroidal-polyhedron-quot-by-dr-ozan-yarman-http-www-ozanyarman-com-">
</a>"Toroidal Polyhedron" (by Dr. Ozan Yarman @ <a href=
"http://www.ozanyarman.com">http://www.ozanyarman.com</a> )</h1>
<h1><a class="anchor" name=
"based-on-the-original-quot-torus-quot-code-by-mark-meyer-" href=
"#based-on-the-original-quot-torus-quot-code-by-mark-meyer-" id=
"based-on-the-original-quot-torus-quot-code-by-mark-meyer-"></a>Based
on the original "Torus" code by Mark Meyer @</h1>
<h1><a class="anchor" name=
"https-www-nodebox-net-code-index-php-mark_meyer_-7c_parametric_surfaces_-7c_torus"
href=
"#https-www-nodebox-net-code-index-php-mark_meyer_-7c_parametric_surfaces_-7c_torus"
id=
"https-www-nodebox-net-code-index-php-mark_meyer_-7c_parametric_surfaces_-7c_torus">
</a><a href=
"https://www.nodebox.net/code/index.php/Mark_Meyer_%7c_Parametric_surfaces_%7c_torus">https://www.nodebox.net/code/index.php/Mark_Meyer_%7c_Parametric_su...</a></h1>
<p>size(486, 486)<br>
background(1)<br>
nofill()<br>
stroke(0.6, 5.6, 1.7, 0.35)<br>
strokewidth(1.0)</p>
<p>translate(WIDTH/2, HEIGHT/2)</p>
<h1><a class="anchor" name=
"n-defines-how-many-vertices-we-find-the-number-will-be-n-2-" href=
"#n-defines-how-many-vertices-we-find-the-number-will-be-n-2-" id=
"n-defines-how-many-vertices-we-find-the-number-will-be-n-2-"></a>n
defines how many vertices we find: the number will be n^2.</h1>
<h1><a class="anchor" name=
"large-values-of-n-can-take-a-while-to-render-" href=
"#large-values-of-n-can-take-a-while-to-render-" id=
"large-values-of-n-can-take-a-while-to-render-"></a>Large values of
n can take a while to render!</h1>
<h1><a class="anchor" name=
"utilize-only-integer-numbers-for-n-w-q-" href=
"#utilize-only-integer-numbers-for-n-w-q-" id=
"utilize-only-integer-numbers-for-n-w-q-"></a>Utilize only integer
numbers for n, w, q.</h1>
<p>n = 10 # number of sides along the axis of revolution<br>
m = 6 # number of sides around the poloidal axis<br>
q = float(n)/m<br>
w = float(n)/n</p>
<h1><a class="anchor" name="-torus-equation-" href=
"#-torus-equation-"></a>--- TORUS EQUATION
--------------------------------------------------------</h1>
<h1><a class="anchor" name=
"define-parametric-equations-for-each-axis-" href=
"#define-parametric-equations-for-each-axis-" id=
"define-parametric-equations-for-each-axis-"></a>Define parametric
equations for each axis.</h1>
<h1><a class="anchor" name="although-we-define-an-z-coordinate-"
href="#although-we-define-an-z-coordinate-" id=
"although-we-define-an-z-coordinate-"></a>Although we define an z
coordinate,</h1>
<h1><a class="anchor" name=
"it-is-only-used-in-transformations-and-shading-" href=
"#it-is-only-used-in-transformations-and-shading-" id=
"it-is-only-used-in-transformations-and-shading-"></a>it is only
used in transformations and shading;</h1>
<h1><a class="anchor" name="it-is-not-used-in-the-drawing" href=
"#it-is-not-used-in-the-drawing" id=
"it-is-not-used-in-the-drawing"></a>it is not used in the
drawing</h1>
<h1><a class="anchor" name=
"-although-it-could-be-if-you-wanted-to-add-perspective-" href=
"#-although-it-could-be-if-you-wanted-to-add-perspective-"></a>(although
it could be if you wanted to add perspective).</h1>
<p>r1 = 165<br>
r2 = 60<br>
def x(u, v): return (r1 + r2 * cos(v)) * cos(u)<br>
def y(u, v): return (r1 + r2 * cos(v)) * sin(u)<br>
def z(u, v): return r2 * sin(v)</p>
<p>def fit_to_domain(u, v):<br>
u = w * u/n * pi*2 v = q * v/n * pi*2 return u, v</p>
<p>from Numeric import *<br>
def matrix(u, v, index):<br>
u, v = fit_to_domain(u, v) return where(index==0, x(u, v),
where(index==1, y(u,v), where(index==2, z(u,v), 1) ) )</p>
<h1><a class="anchor" name="-matrix-rotation-" href=
"#-matrix-rotation-"></a>--- MATRIX ROTATION
------------------------------------------------------</h1>
<p>def rotate_matrix(matrix, x, y, z):<br>
rot_x = array( ([0, cos(pi*x), -sin(pi*x)], [0, sin(pi*x),
cos(pi*x)], [1, 0, 0] ), Float ) rot_y = array(
([cos(0.05*(pi*e)*y), 0, sin(0.05*(pi*e)*y)], [-sin(0.05*(pi*e)*y),
0, cos(0.05*(pi*e)*y)], [0, 1, 0] ), Float ) rot_z = array(
([sin((pi/e)*z), cos((pi/e)*z), 0], [cos((pi/e)*z), -sin((pi/e)*z),
0], [0, 0, 1] ), Float ) matrix = matrixmultiply(matrix, rot_x)
matrix = matrixmultiply(matrix, rot_y) matrix =
matrixmultiply(matrix, rot_z) return matrix</p>
<h1><a class="anchor" name="-vector-normalization-" href=
"#-vector-normalization-"></a>--- VECTOR NORMALIZATION
-------------------------------------------------</h1>
<p>def length(vector):<br>
return sqrt(vector[0]**2 + vector[1]**2 + vector[2]**2)</p>
<p>def normalize_vector(face):<br>
""" Calculate the normal vector between -1 and 1 for a flat surface
""" norm = cross_product((face[0,0] - face[1,1]), (face[1,0] -
face[0,1])) return norm / length(norm)</p>
<h1><a class="anchor" name="-orthographic-projection-" href=
"#-orthographic-projection-"></a>--- ORTHOGRAPHIC PROJECTION
----------------------------------------------</h1>
<p>def project(rows):<br>
""" Go through the array and draw rectangles. There is probably a
more efficent way to do this. """ for i in range(len(rows) -1): for
j in range(len(rows[i])-1): face = rows[i:i+2, j:j+2] normal =
normalize_vector(face) light_angle = (dot(normal, light)) if
(light_angle < 0): light_angle = 0 fill( light_angle - 1.25,
light_angle + 0.285,<br>
light_angle + 0.4, 1.0 ) # Draw only forward facing facets. if
(dot(view, normal) > 0): beginpath( face[0, 0, 0], face[0, 0, 1]
) lineto( face[1, 0, 0], face[1, 0, 1] ) lineto( face[1, 1, 0],
face[1, 1, 1] ) lineto( face[0, 1, 0], face[0, 1, 1] ) path =
endpath() # Save z with path for later z sorting. path.z =
face[1,0,2]</p>
<h1><a class="anchor" name="-rotation-sliders-" href=
"#-rotation-sliders-"></a>--- ROTATION SLIDERS
-----------------------------------------------------</h1>
<p>var("rot_x", NUMBER, 1.00, -pi, pi)<br>
var("rot_y", NUMBER, pi/4, -pi, pi)<br>
var("rot_z", NUMBER, -e, -pi, pi)</p>
<h1><a class="anchor" name="-lighting-sliders-" href=
"#-lighting-sliders-"></a>--- LIGHTING SLIDERS
-----------------------------------------------------</h1>
<p>var("light_x", NUMBER, 0.50, -1.0, 1.0)<br>
var("light_y", NUMBER, -0.60, -1.0, 1.0)<br>
var("light_z", NUMBER, -0.25, -1.0, 1.0)</p>
<p>light = array([light_x, light_y, light_z], Float)</p>
<h1><a class="anchor" name="-facet-culling-" href=
"#-facet-culling-"></a>--- FACET CULLING
--------------------------------------------------------</h1>
<h1><a class="anchor" name="draw-only-forward-facing-facets-" href=
"#draw-only-forward-facing-facets-" id=
"draw-only-forward-facing-facets-"></a>Draw only forward facing
facets.</h1>
<p>view = array([0, 0, 1], Float)</p>
<p>sphere = fromfunction(matrix, (n+1, n+1, 3))<br>
sphere = rotate_matrix(sphere, rot_x, rot_y, rot_z)<br>
project(sphere)</p>
<h1><a class="anchor" name=
"z-sort-to-avoid-problems-with-overlapping-surfaces-" href=
"#z-sort-to-avoid-problems-with-overlapping-surfaces-" id=
"z-sort-to-avoid-problems-with-overlapping-surfaces-"></a>z-sort to
avoid problems with overlapping surfaces:</h1>
<p>sorted_grobs = list(canvas)<br>
sorted_grobs.sort(lambda p1, p2: cmp(p1.z, p2.z))<br>
canvas._grobs = sorted_grobs</p></div>
Dr. Ozan Yarman
tag:support.nodebox.net,2012-11-01:Comment/35614025
2015-01-02T14:04:38Z
2015-01-02T14:04:39Z
Toroidal Polyhedron code based on "Torus" by Mark Meyer
<div><p>The following decisive corrections to the code improve
functionality, and introduce the missing elements for the
orientation of the generator geometry of the toroidal
cross-section.</p>
<hr>
<h1><a class="anchor" name=
"-quot-toroidal-polyhedron-quot-by-dr-ozan-yarman-http-www-ozanyarman-com-"
href=
"#-quot-toroidal-polyhedron-quot-by-dr-ozan-yarman-http-www-ozanyarman-com-">
</a>"Toroidal Polyhedron" (by Dr. Ozan Yarman @ <a href=
"http://www.ozanyarman.com">http://www.ozanyarman.com</a> )</h1>
<h1><a class="anchor" name=
"based-on-the-original-quot-torus-quot-code-by-mark-meyer-" href=
"#based-on-the-original-quot-torus-quot-code-by-mark-meyer-" id=
"based-on-the-original-quot-torus-quot-code-by-mark-meyer-"></a>Based
on the original "Torus" code by Mark Meyer @</h1>
<h1><a class="anchor" name=
"https-www-nodebox-net-code-index-php-mark_meyer_-7c_parametric_surfaces_-7c_torus"
href=
"#https-www-nodebox-net-code-index-php-mark_meyer_-7c_parametric_surfaces_-7c_torus"
id=
"https-www-nodebox-net-code-index-php-mark_meyer_-7c_parametric_surfaces_-7c_torus">
</a><a href=
"https://www.nodebox.net/code/index.php/Mark_Meyer_%7c_Parametric_surfaces_%7c_torus">https://www.nodebox.net/code/index.php/Mark_Meyer_%7c_Parametric_su...</a></h1>
<p>size(486, 486)<br>
background(1)<br>
nofill()<br>
stroke(0.6, 5.6, 2.7, 0.65)<br>
strokewidth(0.5)</p>
<p>translate(WIDTH/2, HEIGHT/2)</p>
<h1><a class="anchor" name=
"n-defines-how-many-vertices-we-find-the-number-will-be-n-2-" href=
"#n-defines-how-many-vertices-we-find-the-number-will-be-n-2-" id=
"n-defines-how-many-vertices-we-find-the-number-will-be-n-2-"></a>n
defines how many vertices we find: the number will be n^2.</h1>
<h1><a class="anchor" name=
"large-values-of-n-can-take-a-while-to-render-" href=
"#large-values-of-n-can-take-a-while-to-render-" id=
"large-values-of-n-can-take-a-while-to-render-"></a>Large values of
n can take a while to render!</h1>
<h1><a class="anchor" name=
"utilize-only-integer-numbers-for-n-and-m-" href=
"#utilize-only-integer-numbers-for-n-and-m-" id=
"utilize-only-integer-numbers-for-n-and-m-"></a>Utilize only
integer numbers for n and m.</h1>
<p>n = 10 # number of sides along the axis of revolution<br>
m = 6 # number of sides around the poloidal axis<br>
k = 4 # normalized phase of generator around the axis of
revolution<br>
q = float(n)/m<br>
w = float(n)/n</p>
<h1><a class="anchor" name="-torus-equation-" href=
"#-torus-equation-"></a>--- TORUS EQUATION
--------------------------------------------------------</h1>
<h1><a class="anchor" name=
"define-parametric-equations-for-each-axis-" href=
"#define-parametric-equations-for-each-axis-" id=
"define-parametric-equations-for-each-axis-"></a>Define parametric
equations for each axis.</h1>
<h1><a class="anchor" name="although-we-define-an-z-coordinate-"
href="#although-we-define-an-z-coordinate-" id=
"although-we-define-an-z-coordinate-"></a>Although we define an z
coordinate,</h1>
<h1><a class="anchor" name=
"it-is-only-used-in-transformations-and-shading-" href=
"#it-is-only-used-in-transformations-and-shading-" id=
"it-is-only-used-in-transformations-and-shading-"></a>it is only
used in transformations and shading;</h1>
<h1><a class="anchor" name="it-is-not-used-in-the-drawing" href=
"#it-is-not-used-in-the-drawing" id=
"it-is-not-used-in-the-drawing"></a>it is not used in the
drawing</h1>
<h1><a class="anchor" name=
"-although-it-could-be-if-you-wanted-to-add-perspective-" href=
"#-although-it-could-be-if-you-wanted-to-add-perspective-"></a>(although
it could be if you wanted to add perspective).</h1>
<p>r1 = 155<br>
r2 = 60<br>
def x(u, v): return (r1 + r2 * cos(v)) * cos(u)<br>
def y(u, v): return (r1 + r2 * cos(v)) * sin(u)<br>
def z(u, v): return r2 * sin(v)</p>
<p>def fit_to_domain(u, v):<br>
u = w * u/n * pi*2 v = q * v/n * pi*2 + ((k*pi)/(2*m)) return u,
v</p>
<p>from Numeric import *<br>
def matrix(u, v, index):<br>
u, v = fit_to_domain(u, v) return where(index==0, x(u, v),
where(index==1, y(u,v), where(index==2, z(u,v), 1) ) )</p>
<h1><a class="anchor" name="-matrix-rotation-" href=
"#-matrix-rotation-"></a>--- MATRIX ROTATION
------------------------------------------------------</h1>
<p>def rotate_matrix(matrix, x, y, z):<br>
rot_x = array( ([0, cos(pi*x), -sin(pi*x)], [0, sin(pi*x),
cos(pi*x)], [1, 0, 0] ), Float ) rot_y = array( ([cos((pi/e**2)*y),
0, sin((pi/e**2)*y)], [-sin((pi/e**2)*y), 0, cos((pi/e**2)*y)], [0,
1, 0] ), Float ) rot_z = array( ([sin((pi/e)*z), cos((pi/e)*z), 0],
[cos((pi/e)*z), -sin((pi/e)*z), 0], [0, 0, 1] ), Float ) matrix =
matrixmultiply(matrix, rot_x) matrix = matrixmultiply(matrix,
rot_y) matrix = matrixmultiply(matrix, rot_z) return matrix</p>
<h1><a class="anchor" name="-vector-normalization-" href=
"#-vector-normalization-"></a>--- VECTOR NORMALIZATION
-------------------------------------------------</h1>
<p>def length(vector):<br>
return sqrt(vector[0]**2 + vector[1]**2 + vector[2]**2)</p>
<p>def normalize_vector(face):<br>
""" Calculate the normal vector between -1 and 1 for a flat surface
""" norm = cross_product((face[0,0] - face[1,1]), (face[1,0] -
face[0,1])) return norm / length(norm)</p>
<h1><a class="anchor" name="-orthographic-projection-" href=
"#-orthographic-projection-"></a>--- ORTHOGRAPHIC PROJECTION
----------------------------------------------</h1>
<p>def project(rows):<br>
""" Go through the array and draw rectangles. There is probably a
more efficent way to do this. """ for i in range(len(rows) -1): for
j in range(len(rows[i])-1): face = rows[i:i+2, j:j+2] normal =
normalize_vector(face) light_angle = (dot(normal, light)) if
(light_angle < 0): light_angle = 0 fill( light_angle - 0.3,
light_angle + 0.28,<br>
light_angle + 0.4, 0.975 ) # Draw only forward facing facets. if
(dot(view, normal) > 0): beginpath( face[0, 0, 0], face[0, 0, 1]
) lineto( face[1, 0, 0], face[1, 0, 1] ) lineto( face[1, 1, 0],
face[1, 1, 1] ) lineto( face[0, 1, 0], face[0, 1, 1] ) path =
endpath() # Save z with path for later z sorting. path.z =
face[1,-2,2]</p>
<h1><a class="anchor" name="-rotation-sliders-" href=
"#-rotation-sliders-"></a>--- ROTATION SLIDERS
-----------------------------------------------------</h1>
<p>var("rot_x", NUMBER, 1.00, -pi, pi)<br>
var("rot_y", NUMBER, pi/4, -pi, pi)<br>
var("rot_z", NUMBER, -e, -pi, pi)</p>
<h1><a class="anchor" name="-lighting-sliders-" href=
"#-lighting-sliders-"></a>--- LIGHTING SLIDERS
-----------------------------------------------------</h1>
<p>var("light_x", NUMBER, 0.50, -1.0, 1.0)<br>
var("light_y", NUMBER, -0.60, -1.0, 1.0)<br>
var("light_z", NUMBER, -0.25, -1.0, 1.0)</p>
<p>light = array([light_x, light_y, light_z], Float)</p>
<h1><a class="anchor" name="-facet-culling-" href=
"#-facet-culling-"></a>--- FACET CULLING
--------------------------------------------------------</h1>
<h1><a class="anchor" name="draw-only-forward-facing-facets-" href=
"#draw-only-forward-facing-facets-" id=
"draw-only-forward-facing-facets-"></a>Draw only forward facing
facets.</h1>
<p>view = array([0, 0, 2], Float)</p>
<p>sphere = fromfunction(matrix, (n+1, m+1, 3))<br>
sphere = rotate_matrix(sphere, rot_x, rot_y, rot_z)<br>
project(sphere)</p>
<h1><a class="anchor" name=
"z-sort-to-avoid-problems-with-overlapping-surfaces-" href=
"#z-sort-to-avoid-problems-with-overlapping-surfaces-" id=
"z-sort-to-avoid-problems-with-overlapping-surfaces-"></a>z-sort to
avoid problems with overlapping surfaces:</h1>
<p>sorted_grobs = list(canvas)<br>
sorted_grobs.sort(lambda p1, p2: cmp(p1.z, p2.z))<br>
canvas._grobs = sorted_grobs</p></div>
Dr. Ozan Yarman