diff --git a/IMG_20200426_151126873.jpg b/IMG_20200426_151126873.jpg
new file mode 100644
index 0000000..b91d5fd
Binary files /dev/null and b/IMG_20200426_151126873.jpg differ
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6e0380a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# 3DprintParametricShape
+added 3D-print option (aka STL output) to Parametric Surface example.
+
+Used it to print möbius band inspired shape; ellips moved+rotated along circle:
+
+
+You need to websearch for "repair STL" too, as the result will have a gap (which is a problem for your 3D-printer, even though you don't see it on your screen)
diff --git a/Three.js/Graphulus-Surface.html b/Three.js/Graphulus-Surface.html
index 3ac6f38..42ae7c0 100644
--- a/Three.js/Graphulus-Surface.html
+++ b/Three.js/Graphulus-Surface.html
@@ -21,6 +21,9 @@
+
+
+
@@ -277,7 +280,7 @@
gui_xText.setValue("cos(u)*(a + b*cos(v))");
gui_yText.setValue("sin(u)*(a + b*cos(v))");
gui_zText.setValue("b*sin(v)");
- gui_uMin.setValue(0); gui_uMax.setValue(6.283);
+ gui_uMin.setValue(0); gui_uMax.setValue(6.283); // please add option to CLOSE design, repeat first value at the end. Now the design is leak, which gives problems when trying to 3D-print it.
gui_vMin.setValue(0); gui_vMax.setValue(6.283);
gui_a.setValue(3);
gui_b.setValue(1);
@@ -309,9 +312,9 @@
function update()
{
- if ( keyboard.pressed("z") )
+ if ( keyboard.pressed("p") )
{
- // do something
+ var myStlString = stlFromGeometry( graphGeometry, {download:true, useObjectPosition:false} ) // maybe a proper button too?
}
controls.update();
diff --git a/Three.js/js/THREE2STL.js b/Three.js/js/THREE2STL.js
new file mode 100644
index 0000000..018f29f
--- /dev/null
+++ b/Three.js/js/THREE2STL.js
@@ -0,0 +1,86 @@
+function stlFromGeometry( geometry, options ) {
+
+ // calculate the faces and normals if they are not yet present
+ geometry.computeFaceNormals()
+
+ var addX = 0
+ var addY = 0
+ var addZ = 0
+ var download = false
+
+ if ( options ) {
+ if ( options.useObjectPosition ) {
+ addX = geometry.mesh.position.x
+ addY = geometry.mesh.position.y
+ addZ = geometry.mesh.position.z
+ }
+
+ if ( options.download ) {
+ download = true
+ }
+ }
+
+
+ var facetToStl = function( verts, normal ) {
+ var faceStl = ''
+ faceStl += 'facet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'
+ faceStl += 'outer loop\n'
+
+ for ( var j = 0; j < 3; j++ ) {
+ var vert = verts[j]
+ faceStl += 'vertex ' + (vert.x+addX) + ' ' + (vert.y+addY) + ' ' + (vert.z+addZ) + '\n'
+ }
+
+ faceStl += 'endloop\n'
+ faceStl += 'endfacet\n'
+
+ return faceStl
+ }
+
+ // start bulding the STL string
+ var stl = ''
+ stl += 'solid\n'
+
+ for ( var i = 0; i < geometry.faces.length; i++ ) {
+ var face = geometry.faces[i]
+
+ // if we have just a griangle, that's easy. just write them to the file
+ if ( face.d === undefined ) {
+ var verts = [
+ geometry.vertices[ face.a ],
+ geometry.vertices[ face.b ],
+ geometry.vertices[ face.c ]
+ ]
+
+ stl += facetToStl( verts, face.normal )
+
+ } else {
+ // if it's a quad, we need to triangulate it first
+ // split the quad into two triangles: abd and bcd
+ var verts = []
+ verts[0] = [
+ geometry.vertices[ face.a ],
+ geometry.vertices[ face.b ],
+ geometry.vertices[ face.d ]
+ ]
+ verts[1] = [
+ geometry.vertices[ face.b ],
+ geometry.vertices[ face.c ],
+ geometry.vertices[ face.d ]
+ ]
+
+ for ( var k = 0; k<2; k++ ) {
+ stl += facetToStl( verts[k], face.normal )
+ }
+
+ }
+ }
+
+ stl += 'endsolid'
+
+ if ( download ) {
+ document.location = 'data:Application/octet-stream, ' + encodeURIComponent( stl )
+ }
+
+ return stl
+}