The OpenSCAD library pointsandfaces

by Philipp Klostermann

Introduction

Most modules, that create basic objects, like cylinder() or cube(), just create them and any further modification can only be done by primitive operations like cutting away parts with intersection() or difference(). There is, for instance, no way to tell a cube to have a narrower top or a cylinder to bend 90°.

I thought it would be nice to have more influence on the shape of objects to be designed, and I found a way to accomplish this in the OpenSCAD module polyhedron(). If you don’t know about polyhedron(), look it up now.

The module polyhedron ist the most powerful in OpenSCAD and thus the most difficult to use, too.

Most designs or modules, that use polyhedron(), do this in a rather static manner. The faces, i.e. the triangles or (with OpenSCAD versions 2014.03 and later) polygons, that define the surface of an object are hardcoded manually and in many cases a lot of instances of the resulting shape are put together via union() to build one more complex object.

So without any functions to generate the amounts of data that polyhedron() needs to make objects with more complexity than a pyramid or an irregular cuboid, polyhedron() is havoc. While calculating the positions of the points is comparably simple in most cases, finding the proper indexes for the faces parameter can be very annoying.

So I wrote my own data-generating functions for different objects, and soon found myself copying and modifying my own code. Experience as a programmer tells me that this means that modularization is required, and I made very basic atomic functions to generate pieces of objects to be assembled to complete faces-arrays and implemented the different objects using these atomic functions.

There are atomic functions to create own types of objects and top-level functions to easily create objects of predefined types.
I restricted myself to only use triangles for faces, i.e. every vector in faces-arrays has 3 elements in the pointsandfaces library. This has mainly two reasons: First, I want to avoid a number of problems, that have to do with the restriction, that all the points of a face have to be in a plane in 3-dimensional space, and second, I want to keep everything easily portable to older OpenSCAD-versions, that may be found on Debian boxes, for instance.

So in the context of pointsandfaces, the word face means a vector of three positive integer numbers, that are indexes for a given array of points.
The meaning of the word point depends on thew context. If we talk about a polygon, we are in 2-dimensional space and it refers to a vector with two real numbers, an x- and a y-coordinate. If we talk about a polyhedron, we are in 3-dimensional space and the word point refers to a vector with three real numbers, an x-, a y and a z-coordinate.

The principle of using the top-level functions is mostly equal:

  • You call the function from the pointsandfaces-library which returns a vector containing an array with the points, an array with the faces, and in some cases a third element, a value for the convexity parameter. You can recognize these functions by the postfix _pnf_v in their names.

  • Optionally, you create a modified version of the positions of the points in the first element of the vector to alter the shape of the object.

  • You call polyhedron() with this data.

    The first example introduces the simplest top-level  function, pnf_tube_pnf_v().