Skip to content

thehans/FunctionalOpenSCAD

Repository files navigation

Functional OpenSCAD

Implementing OpenSCAD in OpenSCAD

Introduction

This library is an attempt to re-implement OpenSCAD's builtin modules as functions which operate directly on vertex data.

Having access to vertex, path, and face geometry data makes it possible to extend the functionality of OpenSCAD from within a user script.

For example, this library includes function bounds(poly) which returns [[minX,minY,minZ],[maxX,maxY,maxZ]] representing the max and min coordinates of all points that make up a shape or list of shapes This sort of calculation is not possible when using builtin modules because their vertex data is not accessible.

Functions vs Modules

To understand what this library is doing, its important to note the distinction between functions and modules in OpenSCAD. See the relevant OpenSCAD documentation if you need a introduction / refresher to these concepts.

The functions in this library have the same names as the builtin OpenSCAD modules that they emulate, but that doesn't mean the builtins are overriden. The OpenSCAD language keeps separate namespaces for functions and modules, and distinguishes between the two based on syntax and context.

Functions always return a value result:

poly = square([1,2]);  // result assigned to variable
poly2d(square([1,2])); // result passed as parameter to a module

In the code above, calls to square are expected to return a value, so OpenSCAD knows to call the square function from our library

Modules can't be passed as parameters, and can't be assigned to variables. Module calls are valid statements by themselves:

square();

Since the call to square above is not stored in a variable or passed as parameter, OpenSCAD knows to use the builtin square module.

The poly "datatype"

The functions in this library operate on geometric data in a special format which we call a poly. It is called this because it can represent either a polygon or polyhedron. I use quotations around "datatype" because OpenSCAD does not have user-defined types. It's just some nested lists(or "vectors") that we can interpret as shapes or vertices. Functions for the geometric primitives always return a poly. Functions that operation on existing shapes (eg transformations) always take poly as the last parameter, and return a poly.

The formats supported are:

  • poly=[points, paths] for 2D shapes. Same format as used by polygon
  • poly=[points, faces] for 3D shapes. Same format as used by polyhedron
  • poly=points just a list of points. Depending on how it is used, it may represent a 2D polygon, or some partial path that will later be concatenated with other paths to form a whole polygon, etc.

Additionally, a poly may represent a "poly vector" (list of polys), which most functions will also accept:

  • poly = [ [points, faces], [points2, faces2], ...]
  • poly = [ [points, paths], [points2, paths2], ...]

In OpenSCAD, functions can not have or interact with children in the way that OpenSCAD modules do. Therefore we must pass our poly data as the last parameter for all Transformation functions, etc.

API Reference

Library Files

functional.scad
The core of FunctionalOpenSCAD. All functions that implement OpenSCAD builtins are contained in this file, plus a few utilities and extras
alternative_spheres.scad
Alternative implementations of spherical geometries, using different methods of tesselation, (eg. subdivided icosahedron).
double_fillet.scad
Provides double_fillet function which generates a smooth transition between two parallel surfaces.
planes.scad
Functions relating to geometric planes.
subdivision.scad
Provides subdivision function which splits each triangle in a 3D poly into 4 smaller triangles by adding midpoints. Included by alternatives_spheres.scad
webbing.scad
Implements "webbing" function which is a way to connect two separate circles with a smooth transition to a thin section between them.

functional.scad

All functions here are intended to behave identically to their OpenSCAD builtin counterparts, however some may have additional parameters. The already mentioned poly parameter is always required when present. Any other parameters have been added as convenience features to enhance default functionality, and are completely optional. All parameters not part of OpenSCAD builtins are marked in bold to distinguish them.

OpenSCAD Builtin Modules Implemented as Functions

2D Primitives

  • square(size=1, center=false, r=0)
  • circle(r=1, c=[0,0], internal=false, d)

3D Primitives

  • cube(size=1, center=false)
  • sphere(r=1, d)
  • cylinder(h=1, r1, r2, center=false, r, d, d1, d2)

2D to 3D

  • linear_extrude(height=100, center=false, convexity=1, twist=0, slices, scale=1.0, poly)
  • rotate_extrude(angle=360, offsetAngle=0, center=false, v_offset=0, i_offset=0, poly)

Transforms

  • scale(v, poly)
  • resize(newsize, poly)
  • rotate(a, v, poly)
  • translate(v, poly)
  • mirror(normal, poly)
  • multmatrix(M, poly)

Functional Extras (no equivalent OpenSCAD Builtin)

Extra Functions

  • arc(r=1, angle=360, offsetAngle=0, c=[0,0], center=false, internal=false)
  • bounds(poly)
  • invert(poly)
  • signed_area(points)
  • signed_volume(poly)

Extra Modules

  • poly3d(poly)
  • poly2d(poly)
  • showPoints(poly, r=0.1)

OpenSCAD Builtin Modules NOT (yet) Implemented as Functions

3D to 2D

Transform

Booleans

alternative_spheres.scad

sphere2(r=1, d)
Simplest sphere implementation, where poles come to points(very slightly different geometry from builtin)
normalized_cube(r=1,div_count=12,d)
Sphere from a simple cube mapping
spherified_cube(r=1,origin=[0,0,1],div_count=12,d)
Sphere from a more balanced cube mapping
icosahedron(r=1,d,n=0)
Subdivided icosahedron mapping (geodesic sphere).
  • n = subdivision iterations. (number of faces = 20 * 4^n)

double_fillet.scad

double_fillet(h=1, r1=1, r2=1, xoffset1=0, xoffset2=0, closed=true)
Double Fillet generates a path that is a smooth transition between two parallel surfaces
  • h is the vertical distance between surfaces, negative height will mirror about the vertical axis
  • r1 and r2 are the first and second fillet radius traversing away from origin
  • xoffset1 distance from origin where first radius begins ( should be >= 0 )
  • xoffset2 distance from edge of first radius to the start of second radius. 0 value makes straight wall, < 0 makes overhang
  • closed = true will return a closed polygon ready for extrusion, while cloesd == false returns a just the curved vertex path that can be use as part of a larger path

planes.scad

function planeFromPoints(a, b, c)
Create a plane from any 3 points.
function planeFromFace(poly, iface, lasti=2)
Find the plane tangent to a specific polyhedron face.
module showPlane(plane, size=[100,100,0.05])
Visualize a plane as a finite thin cube.
function splitPolygonByPlane(plane, polyh, iface)
Atttempted port of OpenJSCAD / csg.js "splitPolygonByPlane" function, prerequisit for further development of boolean operations, projection, etc.

returns [front, coplanarFront, coplanarBack, back] each containing a list of points, or nan

INCORRECT IMPLEMENTATION, NEEDS DEBUGGING

subdivision.scad

subdivide_faces(n=1, poly)
Subdivide each triangle in `poly` into 4 smaller triangles. Additional points are created but the volume remains unchanged by this function.
  • n = subdivision iterations. (number of faces = 20 * 4^n)

webbing.scad

webbing(d1, d2, c2, th, r3)
Draw two circles connected by a continuous curve that necks down to a minimum thickness th.
  • d1 = diameter of 1st circle
  • d2 = diameter of 2nd circle
  • c2 = an [x,y] translation pair for 2nd circle
  • th = minimum thickness of webbing between circles
  • r3 = optionally override the radius calculated for th

About

Implementing OpenSCAD in OpenSCAD

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published