Paso 3: Esferas geodésicas
Ahora vamos a ver en cómo subdividir una esfera en un número determinado de
triángulos de forma aproximadamente similar. El método aquí descrito es
utiliza a menudo para construir aproximaciones poligonales de las esferas, tal como detalla
en este tutorial de OpenGL: http://www.opengl.org.ru/docs/pg/0208.html.
En nuestro caso, esto será el paso de la construcción para generar los agujeros que
transfrom nuestro regular bola en un geodeome-como.
Primero empezamos con un isocahedron regular , que tiene veinte caras triangulares, y
la interesante propiedad de que cada uno de sus vértices se encuentran sobre una esfera.
A continuación, para cada triángulo, nos dividimos cada uno de los tres bordes en el centro, que
nos da tres vértices adicionales que utilizamos para subdividir dicho triángulo
en cuatro triángulos más pequeños. Los tres vértices se traducen entonces hacia el exterior
por lo que se encuentran en la superficie de la esfera.
Script Isocahedron OpenJSCAD
function main(){ var X = 0.525731112119133606; var Z = 0.850650808352039932; var radius = 20; var vdata = [ [-X, 0.0, Z], [ X, 0.0, Z ], [ -X, 0.0, -Z ], [ X, 0.0, -Z ], [ 0.0, Z, X ], [ 0.0, Z, -X ], [ 0.0, -Z, X ], [ 0.0, -Z, -X ], [ Z, X, 0.0 ], [ -Z, X, 0.0 ], [ Z, -X, 0.0 ], [ -Z, -X, 0.0 ] ]; // isocahedron vertex coordinates var tindices = [ [0, 4, 1], [ 0, 9, 4 ], [ 9, 5, 4 ], [ 4, 5, 8 ], [ 4, 8, 1 ], [ 8, 10, 1 ], [ 8, 3, 10 ], [ 5, 3, 8 ], [ 5, 2, 3 ], [ 2, 7, 3 ], [ 7, 10, 3 ], [ 7, 6, 10 ], [ 7, 11, 6 ], [ 11, 0, 6 ], [ 0, 1, 6 ], [ 6, 1, 10 ], [ 9, 0, 11 ], [ 9, 11, 2 ], [ 9, 2, 5 ], [ 7, 2, 11 ] ]; // isocahedron triangles return polyhedron({ points: vdata, triangles: tindices }).scale([radius, radius, radius]); }
A continuación escribimos la función de la subdivisión para una aproximación de la esfera de unidad:
La función de subdvide
/* fn subdivide(v1, v2, v3, addPolyCb, depth) * brief subdivides a triangle into 4 smaller ones * params v1, v2, v3 : triangle vertices * addPolyCb : callback for add polygon notification * depth : number of remaining subdivision iterations */ function subdivide(v1, v2, v3, addPolyCb, depth) { if(depth == 0) { addPolyCb(v1, v2, v3); return; } var v12 = v1.plus(v2).unit(); // middle of v1v2 edge projected on the unit sphere var v23 = v2.plus(v3).unit(); var v31 = v3.plus(v1).unit(); var newDepth = depth - 1; subdivide(v1, v12, v31, addPolyCb, newDepth); subdivide(v2, v23, v12, addPolyCb, newDepth); subdivide(v3, v31, v23, addPolyCb, newDepth); subdivide(v12, v23, v31, addPolyCb, newDepth); }
El proceso de subdivisión funciona de forma recursiva; a partir de las 20 isocahedron
caras, cada paso de la subdivisión multiplica al número total de caras 4.
Por lo tanto, una profundidad de 1 genera un Poliedro de 80 caras.
Ahora podemos generar una aproximación de la esfera mediante una llamada a la función de subdividir
iterativamente sobre las caras de isocahedron como sigue:
80 caras esfera geodésica script
function main() { var ballDiameter = 40; var ballRadius = ballDiameter/2.; var polygons = []; // list of polygons addPolyCb = function(v1, v2, v3) { polygons.push(new CSG.Polygon([ new CSG.Vertex(new CSG.Vector3D(v3.x,v3.y,v3.z)), new CSG.Vertex(new CSG.Vector3D(v2.x,v2.y,v2.z)), new CSG.Vertex(new CSG.Vector3D(v1.x,v1.y,v1.z)) ])); } createGeodesicSphere(addPolyCb, 1); var unitSphereApprox = CSG.fromPolygons(polygons); return unitSphereApprox.scale([ballRadius, ballRadius, ballRadius]); } // subdivides a unit isocahedron n=depth times and calls a callback for each created face function createGeodesicSphere(addPolyCb, depth) { var X = 0.525731112119133606; var Z = 0.850650808352039932; var vdata = [ [-X, 0.0, Z], [ X, 0.0, Z ], [ -X, 0.0, -Z ], [ X, 0.0, -Z ], [ 0.0, Z, X ], [ 0.0, Z, -X ], [ 0.0, -Z, X ], [ 0.0, -Z, -X ], [ Z, X, 0.0 ], [ -Z, X, 0.0 ], [ Z, -X, 0.0 ], [ -Z, -X, 0.0 ] ]; var tindices = [ [0, 4, 1], [ 0, 9, 4 ], [ 9, 5, 4 ], [ 4, 5, 8 ], [ 4, 8, 1 ], [ 8, 10, 1 ], [ 8, 3, 10 ], [ 5, 3, 8 ], [ 5, 2, 3 ], [ 2, 7, 3 ], [ 7, 10, 3 ], [ 7, 6, 10 ], [ 7, 11, 6 ], [ 11, 0, 6 ], [ 0, 1, 6 ], [ 6, 1, 10 ], [ 9, 0, 11 ], [ 9, 11, 2 ], [ 9, 2, 5 ], [ 7, 2, 11 ] ]; // iterate over isocahedron triangles for(var i = 0; i < 20; i++) subdivide( new CSG.Vector3D(vdata[tindices[i][0]]), new CSG.Vector3D(vdata[tindices[i][1]]), new CSG.Vector3D(vdata[tindices[i][2]]), addPolyCb, depth); }
Para ejecutar esta secuencia de comandos, copie y pegue el código en tu editor de código favorito y guarde
el archivo con la extensión .jscad. Entonces simplemente arrastrar y soltar el archivo en el recangular
área en la esquina inferior izquierda de la ventana del navegador OpenJSCAD.