Class: Shape

PD. Shape

A simple and efficient class for defining and operating on manifold facetted shapes.

This class is a much simpler and leaner version of the PD.BRep and PD.Shell classes. Shapes are assembled from a set of spatial vertices defined as [x,y,z] vector arrays that are shared by the boundaries of planar faces that reference them by index. These planar faces should typically form a topologically closed (manifold) shape that completely bounds an internal volume of space.

It is possible to create shapes that are not topologically closed, do not have planar faces or do not share common vertices between connected faces. However, many of the analysis and modifier methods in this class, as well as the external computations that use them, do assume that manifold conditions will be met as the ability to create and manipulate closed faceted shapes really is the core raison d'etre of this class.

Thus, you can use this class any way you wish for interim geometry or to store data temporarily, but if you want to use the built-in modifiers or have the shape participate in computations or analysis, you should strive to ensure that the final result is topologically closed, uses shared vertices and has planar facets.

Topologically Closed

To be topologically closed means that the shape completely bounds an internal volume with faces that are all connected together at their edges and share common vertices. This is also called a manifold shape and means that every vertex must be shared by at least three edges and every edge must be shared by exactly two faces. Each face must be defined by a single outer boundary loop of vertex indices. A face in a shape cannot contain internal hole boundaries, but must instead be broken down into a series of separate faces that bound the hole.

Array-Based Vertices

A very important characteristic of this class is that all vertices are and must be stored as [x,y,z] vector arrays rather than point objects. Using array-based vertices and faces actually makes this data structure enormously flexible and efficient as an interim format for creating, modifying and storing closed faceted shapes. Obviously primitive shapes are at its core, but this also includes those with highly faceted curved surfaces and forms derived from volumetric grids.

This is mainly because each triangle or quad is just an array of three or four integer ordinal indexes, and every vertex is spatially unique and just an array of three numbers. Also, as long as the first three entries in each vertex array always remain as its x, y and z coordinates, external processes can append additional entries to the array for things like vertex normals, colors, UV and even extra coordinates to morph the shape between. Obviously this additional information will not always be retained if you then go on to apply modifiers that changes the geometry of the shape.

Another important point is that this class does not provide any built-in way to reuse its existing memory, and does not store face normals, triangulation or shared edge data. These are all calculated when required by calling the normals(), edges() and vertexNormals() methods. This makes it not well suited for storing geometry that needs to be regularly converted to a renderable mesh, which is why the PD.BRep and PD.Shell classes are used for that purpose by the framework.

Also, whilst you can compute and store per-vertex normals if you really want to, this is not a particularly good class for working with multiple connected smoothly curved surfaces. Many of its core applications rely on having unique vertices shared between polygonal faces as a way to determine inter-connection relationships. As a vertex can only store a single normal direction, those shared by faces with sharply different normal directions will only be able to represent one of them, or have an averaged normal that actually reflects none of them. This can be useful for offsetting 3D geometry, but not for displaying it. The only option is to have separate vertices for each face, but that will break all inter-connection calculations.

As a result, this class is mainly used by the framework for creating interim geometry that can take advantage of the unique characteristics of this format and its ability to efficiently modify, process and transform basic shapes, that is then converted to and stored as either a PD.BRep and PD.Shell. When used this way, you can iteratively create amazing and complex geometric forms and only have to compute surface normals, extents and other metrics on the final shape.

To assist with the array-based vector math involved in the creation, modification and transformation of these kinds of forms, the framework provides the PD.VectorArray, PD.PlaneArray, PD.QuaternionArray and PD.MatrixArray classes. The framework also links to a set of array-based vector geometry libraries for generating 2D and 3D convex hulls, surface triangulations and noise generation.


new Shape( [vertices] [, faces] [, name])

Constructor for an empty shape.

Parameters:
Name Type Argument Description
vertices Array.<Array.<number>> <optional>

A flat array of [x,y,z] vertex coordinates.

faces Array.<Array.<number>> <optional>

An array of face boundary arrays, each containing three or more vertex indices.

name string <optional>

A human-readable name for the shape.

Author:
  • drajmarsh

Classes

Roofs
Shells

Members


:Array.<number>|Array.<Array.<number>>

colors

An array of [r,g,b] face colors.

This array is only valid if it is exactly the same length as the PD.Polyhedron#faces array. Each entry in this array is the color associated with the corresponding face in the faces array.

Type
  • Array.<number> | Array.<Array.<number>>

:Array.<Array.<number>>

faces

An array of face boundary arrays, each containing three or more vertex indices.

Each face is an array of ordinal indices of the vertexes in the PD.Shape#vertices array that form its boundary.

Type
  • Array.<Array.<number>>

:boolean

isShape <readonly>

A flag identifying this object as a shape.

Type
  • boolean

:string

name

A human-readable name for the shape.

Type
  • string

:Array.<Array.<number>>

vertices

A flat array of vertex coordinates stored as [x,y,z] vector arrays.

Each vertex is an array of three (3) numbers representing the X, Y and Z coordinates of a spatial point, referred to as an [x,y,z] vector array. These vertices are assembled into edges and boundaries by the PD.Shape#faces array.

Type
  • Array.<Array.<number>>

:number

indexerDecimals <static>

The default number of decimal places when creating an indexer to amalgamate coincident vertices.

This value defaults to 1 decimal place, which will 'weld' vertices that are within 0.1mm of each other.

However, the PD.Polyhedron class typically works with shapes that have a radius of 1, so it will temporarily set this value to 6 or more during its operations.

Type
  • number

Methods


addVertex(vertex)

Retrieves the next reusable vertex in the surface, or creates and adds a new one.

The argument to this method can be either a simple [x,y,z] vector array or an {x,y,z} object such as a THREE.Vector3, PD.Point or similar object class. This method fetches from or creates vertices in vertexList by incrementing an internal counter that is reset to zero when the reuseStart() method is called.

Parameters:
Name Type Description
vertex Array.<number>

The [x,y,z] vector array to add to the vertex list.

Returns:

Returns the index of the added vertex in the vertices list.

Type
number

align( [alignX] [, alignY] [, alignZ] [, point])

Moves this shape to align it in each axis with the given point.

The axial alignment values are given as fractions of the shape's extents in that axis. A value of zero in any axis means that the shape will align centrally at the point. A value of 1 means that shape will align its minimum edge at the point, and a value of -1 means that it will align its maximum edge. You can use any fractional values (eg: 0.5) or even multiples (eg: 2.5) in any axis.

Parameters:
Name Type Argument Description
alignX number <optional>

The X axis alignment factor (-1 to 1), defaults to 0.

alignY number <optional>

The Y axis alignment factor (-1 to 1), defaults to alignX.

alignZ number <optional>

The Z axis alignment factor (-1 to 1), defaults to alignX.

point Array.<number> <optional>

An [x,y,z] vector array for the point to align with, defaults to origin [0,0,0].

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const box = PD.Shape.cuboid(3000, 2000, 1000);
CAD.add(box.align(1, 1, 1));

ambo( [offset])

The Conway ambo operation is essentially the truncation of a shape by marking the midpoints of all its edges and cutting its vertices at those points.

The best way to think of the ambo operator is as a topological 'tween' between a polyhedron and its dual polyhedron. Thus the ambo of a dual polyhedron is the same as the ambo of the original.

Parameters:
Name Type Argument Description
offset number <optional>

The distance of the pyramid apex away from the face center in model units, defaults to 0.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
/// Cupola-based space frame.
const poly = PD.Shape.cupola(9).scale(6000);
poly.ambo().ambo().triakis(9, 2000).join();
poly.translate([ 0, 0, -1800 ]).scale([ 1, 1, 2 ]).cutAt(0, 1);
const frame = PD.Shape.frame(poly, 250, 150);
CAD.add(frame);

applyAxis(axis)

Aligns this shape with the local coordinate axis.

Parameters:
Name Type Description
axis PD.AxisArray

The local coordinate axis to apply.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
const segments = 12;

/// Create base shape to work on.
const cyl = PD.Shape.cylinder(segments, 1000, 500);

/// Create local coordinates.
const axis = new PD.AxisArray();
axis.moveOrigin(0, 2000, 0);
axis.rotateZ(Math.PI / 4);
cyl.applyAxis(axis);

/// Create different positive/negative scales.
const scale_positive = [3.50, 1.5, 1.0];
const scale_negative = [1.25, 1.5, 1.0];

/// Extract the bottom ring of vertices.
const base = cyl.vertices.slice(0, segments);

/// Apply both scales about the origin.
axis.scalePoints(base, scale_positive, scale_negative);
CAD.add(cyl);

applyMatrix(matrix)

Applies a transformation matrix to this shape.

Parameters:
Name Type Description
matrix Array.<number>

The 16-item (4x4) column-major matrix to apply.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape

applyQuaternion(quaternion)

Applies a rotational quaternion to this shape.

Parameters:
Name Type Description
quaternion Array.<number>

The [x,y,z,w] quaternion to apply.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape

bevel( [sides])

The Conway bevel operation truncates the shape at its edges and vertices, creating a new facet in place of each edge and of each vertex.

If the sides argument is less than 3, all faces in the shape will be bevelled. If 3 or more, only those faces with a matching number of sides will be bevelled.

Parameters:
Name Type Argument Description
sides number <optional>

The number of sides as face must have to be affected, defaults to 0.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(poly.clone().bevel().setRadius(3440));
CAD.add(poly);

centers()

Computes a list of face center points.

The center of each face is returned as an [x,y,z] vector array defining its spatial position in each major axis.

The order and index of center points in the returned list match the order and index of corresponding faces in the faces list.

Returns:

Returns an array of face centers.

Type
Array.<Array.<number>>
Example
const shape = PD.Shape.domeGeodesic(4, 2000)

/// Find bottom face.
let bottom_face_index = -1;
let bottom_face_min_z = Infinity;
const face_centers = shape.centers();
for (let ii = 0; ii < face_centers.length; ++ii) {
    if (bottom_face_min_z > face_centers[ii][2]) {
        bottom_face_min_z = face_centers[ii][2];
        bottom_face_index = ii;
    }
}

/// Show bottom face as face.
if (bottom_face_index >= 0) {
    const points = shape.faces[bottom_face_index].map(index => shape.vertices[index]);
    CAD.addPolygon(points);
}

clone()

Creates a deep copy of this shape.

Returns:

Returns a new shape.

Type
PD.Shape
Example
const shape = PD.Shape.prism(9, 1500, 1000).ortho();
CAD.add(shape.clone().inflate(200));
CAD.add(shape);

closestAndFarthestFromPlane(plane)

Computes the vertex positions that are closest to and farthest away from the given plane.

Parameters:
Name Type Description
plane number | Array.<number>

A [a,b,c,d] plane array or vertical height value in the Z axis to slice the shape at.

Returns:

Returns a [closest,farthest] array of [x,y,z] vector arrays.

Type
Array.<Array.<number>>
Example
const slices = 4;
const plane = [  1,  0.25,  0,  10000 ];
const shape = PD.Shape.cuboid(4000, 2000, 1000);
const [ closest, farthest ] = shape.closestAndFarthestFromPlane(plane);
const start = -PD.VectorArray.dot(closest, plane);
const end = -PD.VectorArray.dot(farthest, plane);
const inc = (end - start) / (slices + 1);

for (let ii = 1; ii <= slices; ++ii) {
    plane[3] = start + (ii * inc);
    shape.cutAt(plane, 0);
}

CAD.addSolid(shape);
const frame = PD.Shape.frame(shape, 50, 50);
CAD.add(frame);

computeCentroid()

Computes the geometric center point of the shape by averaging all of its vertices.

Returns:

Returns the centroid as an [x,y,z] vector arrays.

Type
Array.<number>

connections()

Computes and assembles the connection relationships between faces, edges and vertices.

This method returns an object with two arrays as properties:

  • vertices: An array of vertices with the indexes of each of the other vertices they connect to via an edge. This array is in the form [ v1, v2, v3, ... ] and uses the same ordinal indexes as the PD.Shape#vertices array.

  • edges An array of edges with two vertex indices followed by the indexes of the two faces they share. This array is in the form [ v1, v2, f1, f2 ].

The vertex indexes in the edges array are ordered such that the lowest ordinal index always comes first (array[0]) followed by the highest ordinal (array[1]). The face indexes are ordered such that, in the first face (array[2]), the direction of travel along the edge is from first vertex to second. In the second face (array[3]), the direction of travel is from the second vertex (array[1]) back to the first (array[0]).

Returns:

Returns an array of vertex and edge connections.

Type
Array.<Array.<Array.<number>>>

copy(shape)

Performs a shallow copy of the data in the given shape.

Parameters:
Name Type Description
shape PD.Shape

The shape to copy from.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape

copyToBRep(brep [, scale])

Copies the shape to the given BRep.

Ideally, adding a PD.Shape to a PD.BRep should be done in the PD.BRep class as the PD.Shape class is lower level in the framework. However, not every applications that includes BRep needs to include PD.Shape, so this method is is only required when an application actually includes and uses PD.Shape.

Parameters:
Name Type Argument Description
brep PD.BRep

The BRep to add the shape to.

scale number <optional>

An optional scale factor for the shape, defaults to 1000mm (1m).

Returns:

Returns true if geometry was added to the BRep.

Type
boolean

cutAt(plane [, keep] [, cutFaces])

Cuts the faces of this shape by the given plane and either keeps all of them or just those in the front or behind.

Defining a Plane

This method uses an infinite plane to cut the shape, defined by an [a,b,c,d] plane array based on the Ax + Bx + Cz + D = 0 equation for a 3D plane. This means providing an array with four numbers that define the A, B, C and D components of the equation.

Alternatively, if you just want to cut a shape with a horizontal plane, you can pass a single number rather than a plane array. This number is used as the height on the Z axis of a cutting plane that faces towards the +Z axis.

The first three values in the plane array define its normal direction, which also defines the front and rear sides of the plane. Anything on the same side as the normal is pointing is in front, and anything on the other side is behind.

To make this method easier to use, the directional component of any given plane array does not need to be normalised as this will be done automatically. Thus, you could provide a plane array such as [ 1, 1, 1, -500 ] and it will be automatically normalized to [ 0.5773503, 0.5773503, 0.5773503, -500 ].

NOTE: When providing just a single number instead of a plane, it is important to remember that the number represents the plane height rather than the D component. Thus, a numeric value of 250 is equivalent to specifying [0,0,1,-250] as the plane array.

Which Side

You can choose to retain faces on both sides of the cut, or just those in front of or behind the cutting plane. To do this, set the value of keep to a positive number (usually 1) for faces in front of the plane, a negative number (usually -1) for faces behind the plane, or exactly zero (0) to keep both sides.

Accessing Cut Faces

If the value of keep is not zero, faces will be added to 'fill in' any openings created in the shape by the cut. If you set the value of cutFaces to an existing array, the new faces will be added to this array instead of directly to the shape. These faces will still reference vertices within the shape (which are shared by the existing faces that were actually cut), but this allows you an opportunity to discard or post-process them before adding them to the shape.

One action that is regularly performed on shapes is to do a cut and then extrude the 'fill in' faces in the opposite direction to create a base. As a result, this method provides a shortcut for for you to do this as part of the cutting process by passing a numeric value for cutFaces instead of an array. This numeric value must be positive, as shown in the second example below.

Parameters:
Name Type Argument Description
plane Array.<number> | number

An [a,b,c,d] plane array to cut the shape at or a height value in the +Z axis.

keep number <optional>

Which side(s) of the plane to retain (0:Both, 1:Front, -1:Rear), defaults to 0 (both).

cutFaces Array | number <optional>

An optional array in which to store any newly added cut faces. If given as a positive number instead of an array, it gives a distance by which to create a base by extruding cut surfaces in the opposite direction of the cutting plane.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Examples
const cut_faces = [];
const cut_plane = [ 0, 0, 1, 0 ];
const dome_with_holes = new PD.Polyhedron('D12:jh(0.15,0.025)ajejS9000');
dome_with_holes.cutAt(cut_plane, 1);
CAD.add(dome_with_holes);
/// Extrude cut faces to form support columns.
const cut_faces = [];
const cut_plane = [ 0, 0, 1, 0 ];
const poly = new PD.Polyhedron('D8:jeh(0.15,0.025)ajS9000');
const dome_with_holes = PD.Shape.cutAt(poly, cut_plane, 1, cut_faces).translate([ 0, 0, 3000 ]);
for (const face of cut_faces) {
    dome_with_holes.faceExtrude(face, -3000, cut_plane, 3);
}
CAD.add(dome_with_holes);

dual()

The Conway dual operation creates a new shape in which the centroid of each face in the original shape becomes a new vertex in the dual, and each vertex in the original becomes the centroid of a new face.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(poly.dual());

edges()

Computes a non-redundant list of the shape's edges.

The edges of a shape are simply arrays containing two integer values, being the ordinal indices of the start and end vertices of the edge within the PD.Shape#vertices array.

Returns:

Returns an array of unique edges.

Type
Array.<Array.<number>>
Example
const poly = new PD.Polyhedron('D8:tk').scale(2000);

/// Display polyhedron as wires.
for (const edge of poly.edges()) {
    const points = edge.map(index => poly.vertices[index]);
    CAD.addWire(points, false);
}

/// Cut section and display as a face.
const section = PD.Shape.generateSection(poly, [ -1, -1, 4, -200 ]);
if (section?.faces) {
    CAD.addShell(section);
}

ensureOutwardOrientation()

Iterates the shape to ensure that all faces are oriented outwards relative to the geometric centre of the shape.

A face normal is considered to be pointing inwards if the dot product of its vector towards the centroid is positive, in which case the face is reversed.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape

ensureOutwardOrientation_MoreRobust()

Iterates the shape to ensure that all faces are oriented outwards by referencing a known good face.

This method uses a reference face as a reference and compares all other to it. The reference face is determined as the one with a centre point at the most extreme edge in one of the major cartesian axis. To be facing 'outwards', the normal of the most extreme face in must point in the same direction as that axis. Once this condition is met, all other faces can be oriented relative to that one.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape

expand()

The Conway expand operation is basically a double ambo operation, which is the truncation of a shape by marking the midpoints of all its edges and cutting its vertices at those points.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
/// Cupola-based space frame.
const poly = PD.Shape.anticupola(9).scale(9000);
poly.triakis(9, 2000).expand().join();
poly.translate([ 0, 0, -6700 ]).scale([ 1, 1, 3 ]).cutAt(0, 1);
const frame = PD.Shape.frame(poly, 250, 150);
CAD.add(frame);

extents( [min] [, max])

Computes the minimum and maximum extents of the shape.

Parameters:
Name Type Argument Description
min Array.<number> <optional>

An optional [x,y,z] vector array to receive the minimum extents.

max Array.<number> <optional>

An optional [x,y,z] vector array to receive the maximum extents.

Returns:

Return a [min,max] array of two [x,y,z] vector arrays.

Type
Array.<Array.<number>>
Example
/// Create cylinder with 12 sides and 20 segments.
const shape = PD.Shape.cylinder(12, 2000, 5000, 20);

/// Compute range values in Z axis.
const [ min, max ] = shape.extents();
const bot_z = min[2] + ((max[2] - min[2]) * 0.25);
const top_z = min[2] + ((max[2] - min[2]) * 0.90);

/// Apply a scaling factor over the range.
shape.scaleByAxis(2, bot_z, top_z, 2.0, PD.Easing.inOutQuart);
CAD.add(shape);

extrudeBase(height [, segments])

Searches for the bottom-most face whose normal points in the -Z direction and extrudes it downwards by the given distance (height) and in the given number of segments.

Parameters:
Name Type Argument Description
height number

The height of the base to add to the shape, in model units.

segments number <optional>

The number of segments to extrude the base in, defaults to 1.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

faceCenter(face [, target])

Compute the geometric center of the given face.

The center of the face is returned as an [x,y,z] vector array defining its spatial position in each major axis.

Parameters:
Name Type Argument Description
face number | Array.<number>

The face to process, as an index within the faces array, or the actual array of vertex indices.

target Array.<number> <optional>

An optional [x,y,z] vector array to receive the calculated center, defaults to a new vector array.

Returns:

Return an [x,y,z] vector array defining the face center.

Type
Array.<number>
Example
const shape = PD.Shape.domeGeodesic(4, 2000)

/// Display shape as wires.
for (const edge of shape.edges()) {
    const points = edge.map(index => shape.vertices[index]);
    CAD.addWire(points, false);
}

/// Find bottom face.
const center = [ 0, 0, 0 ];
let bottom_face_index = -1;
let bottom_face_value = Infinity;
for (let ii = 0; ii < shape.faces.length; ++ii) {
    shape.faceCenter(ii, center);
    if (bottom_face_value > center[2]) {
        bottom_face_value = center[2];
        bottom_face_index = ii;
    }
}

/// Show bottom face as face.
if (bottom_face_index >= 0) {
    const points = shape.faces[bottom_face_index].map(index => shape.vertices[index]);
    CAD.addPolygon(points);
}

faceExtrude(face, distance [, direction] [, segments])

Extrudes the given face in the given direction and distance.

This method displaces the given face and adds extruded side faces. If the optional segments argument has an integer value of greater than one (1), the extrusion will be done in a series of that many segments.

Parameters:
Name Type Argument Description
face number | Array.<number>

The face to process, as an index within the faces array, or the actual array of vertex indices.

distance number

The total distance to extrude, in model units.

direction Array.<number> <optional>

The direction to extrude in as an [x,y,z] vector array. defaults to the face's surface normal.

segments number <optional>

The number of segments to extrude the face in, defaults to 1.

Returns:

Return an array of all the new faces just added.

Type
Array.<Array.<number>>
Example
const cut_faces = [];
const cut_plane = [ 0, 0, 1, 0 ];
const poly = new PD.Polyhedron('D8:jeh(0.15,0.025)ajS9000');
const dome_with_holes = PD.Shape.cutAt(poly, cut_plane, 1, cut_faces).translate([ 0, 0, 3000 ]);
for (const face of cut_faces) {
    dome_with_holes.faceExtrude(face, -3000, cut_plane, 3);
}
CAD.add(dome_with_holes);

faceInset(face [, inset] [, offset] [, normal])

Computes a set of vertices inset from the edges of the given face.

Parameters:
Name Type Argument Description
face number | Array.<number>

The face to process, as an index within the faces array, or the actual array of vertex indices.

inset number <optional>

An inset distance from each edge in model units, defaults to 0 (no inset).

offset number <optional>

An optional distance from face surface, defaults to 0 (no offset).

normal Array.<number> <optional>

An optional [x,y,z] vector array to receive the calculated face normal so you don't need to compute it again.

Returns:

Return an array of new inset/offset vertices.

Type
Array.<Array.<number>>

faceNormal(face [, target])

Compute the surface normal of the given face.

The normal vector of the face is returned as an [x,y,z] vector array of unit length (normalized) defining its spatial direction in each major axis.

Parameters:
Name Type Argument Description
face number | Array.<number>

The face to process, as an index within the faces array, or the actual array of vertex indices.

target Array.<number> <optional>

An optional [x,y,z] vector array to receive the calculated normal, defaults to a new vector array.

Returns:

Returns the modified target if it is given or a new [x,y,z] vector array defining the face normal.

Type
Array.<number>
Example
const distance = 250;
const face_normal = [];
for (let ii = 0; ii < shape.faces.length; ++ii) {
    for (const index of shape.faces[ii]) {
        hull_vertices.push(
            PD.VectorArray.translateInVectorDirection([], shape.vertices[index], face_normals[ii], distance)
        );
    }
}

faceVertices(face)

Retrieves the face as an array of actual vertices, being the [x,y,z] vector arrays representing each point on the face boundary.

NOTE: This method returns the actual vertex arrays from the shape vertex list, so any changes you make to the vertex arrays will propagate across all faces that share the same vertices.

Parameters:
Name Type Description
face number | Array.<number>

The face to process, as an index within the faces array, or the actual array of vertex indices.

Returns:

Return an array of [x,y,z] vector array points the define the face boundary.

Type
Array.<Array.<number>>
Example
const shape = PD.Shape.domeGeodesic(4, 2000)

/// Find bottom face and show as filled polygon.
const bot_face = shape.findExtremeFace([ 0, 0, -1 ]);
if (bot_face.index >= 0) {
    const points = shape.faceVertices(bot_face.index);
    CAD.addPolygon(points);
}

/// Show rest of shape as wires.
for (const edge of shape.edges()) {
    const points = edge.map(index => shape.vertices[index]);
    CAD.addWire(points, false);
}

findExtremeFace( [normal])

Finds the face with a centre point at the extreme edge of the shape in one of the major cartesian axis.

This method is used to find a reference face to use for orienting all others. To be facing 'outwards', the normal of the most extreme face in one of the major axis must point in the same direction as that axis.

Parameters:
Name Type Argument Description
normal Array.<number> <optional>

An optional [x,y,z] vector array giving the direction to search in, defaults to any.

Returns:

Returns an object with face, extreme.index and extreme.axis properties, being the actual face, its index in the faces array and the axis (0, 1 or 2).

Type
object
Examples
const { face, index, axis } = shape.findExtremeFace();

/// Ensure extreme face normal points in same direction as extreme axis.
PD.VectorArray.calcNormalFromIndexedPathNewellMethod(normal, face, this.vertices);
if (normal[axis] < 0) {
     face.reverse();
}
const shape = PD.Shape.domeGeodesic(4, 2000)

/// Find bottom face and show as filled polygon.
const bot_face = shape.findExtremeFace([ 0, 0, -1 ]);
if (bot_face.index >= 0) {
    const points = shape.faceVertices(bot_face.index);
    CAD.addPolygon(points);
}

/// Display shape as wires.
for (const edge of shape.edges()) {
    const points = edge.map(index => shape.vertices[index]);
    CAD.addWire(points, false);
}

frame( [inset] [, thickness] [, glazing])

The frame operation essentially hollows out the shape and generates a structural frame with bars running along each of its edges.

Parameters:
Name Type Argument Description
inset number <optional>

The inset width of framing bars, defaults to 25mm.

thickness number <optional>

The framing bar thickness as a positive value, defaults to 50mm.

glazing boolean <optional>

Whether or not to generate glazing panes between frames.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
/// Cupola-based space frame.
const shape = PD.Shape.anticupola(9).scale(9000);
shape.scale([1, 1, 3]).triakis(9, 2000).expand().join();
shape.translate([0, 0, -7500]).cutAt(0, 1);
shape.frame(250, 150);
CAD.add(shape);

fromJSON(data)

Safely copy properties from a source object.

See the PD.Base#fromJSON method for more details.

NOTE: If vertexes are given as [x,y,z] vector arrays, and faces as arrays of ordinal indexes, then both the faces and vertices data arrays are used directly rather than copied to the shape. This makes creating shapes from JSON very fast and efficient, which is important as this class is used quite a lot for data exchange. If you want to deep copy the data arrays, see the example code below:

Parameters:
Name Type Description
data object

The source object containing data to copy.

Returns:

Returns this instance to support method chaining.

Type
PD.Shape
Example
const shallow_copy = new PD.Shape().fromJSON(data);
const deep_copy = new PD.Shape().fromJSON(data).clone();

gyro( [offset] [, fraction])

The Conway gyro operation creates a new shape in which a new face is created at each vertex of its dual, which is then twisted slightly and two new triangular faces added to replace each edges and fill the gaps.

NOTE: When using an offset value not equal to zero, this operation will often create non-planar faces. If that is detected, then the resulting faces will be automatically triangulated.

Parameters:
Name Type Argument Description
offset number <optional>

The distance of the center apex away from the face center in model units, defaults to 0.

fraction number <optional>

The face rotation fraction (0.001 to 0.999), defaults to 1/3.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const shape = PD.Shape.cuboid();
shape.gyro().triangulate().scale(5000);
CAD.add(shape);

hasContent()

Determines whether or not the shape has any content.

This method does a very simple check to see if there are any vertices and any faces. It doesn't do any validity or sanity checking, just looks for content.

Returns:

Returns true if shape has one or more valid edge/facet.

Type
boolean

inflate(distance [, checkPlanes])

Expand all vertices in the direction of their surface normals by the given distance.

Expansion is different from offsetting in that the given distance refers to the movement of each vertex rather than to each face. Vertices move in the direction of their average surface normals, which is effectively the normalised sum of each face normal that the vertex is shared by. Movement is outwards if the distance is positive or inwards if it is negative.

The result is a set of vertices that are exactly the given distance away from their original positions. Depending on the number of faces shared by each vertex, and their relative orientations, this may result in faces changing orientation slightly and not being parallel to their original position. In some rare cases it may even result in faces that are no longer planar.

If you want to specify the exact perturbation distance of faces rather than vertices use the PD.Shape#offset method instead.

Parameters:
Name Type Argument Description
distance number

The expansion distance, defaults to 0.

checkPlanes number <optional>

Extra checks (0:None, 1:OnePlane, 2:AllPlanes), defaults to 0.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
const shape = PD.Shape.prism(9, 1500, 1000).ortho();
CAD.add(shape.clone().inflate(200));
CAD.add(shape);

join()

The Conway join operation is basically an ambo operation performed on the dual of the original shape, then converted back to a dual.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
/// Cupola-based space frame.
const poly = PD.Shape.cupola(9).scale(12000);
poly.join().expand().triakis(9, 2000).join();
poly.translate([ 0, 0, -6700 ]).scale([ 1, 1, 3 ]).cutAt(0, 1);
const frame = PD.Shape.frame(poly, 250, 150);
CAD.add(frame);

loft( [sides] [, inset] [, offset])

The loft operation insets each edge of the specified faces and creates new quad faces to fill the gap.

If the sides argument is less than 3, all faces in the shape will be lofted. If 3 or more, only those faces with a matching number of sides will be lofted.

If an inset value is given, then the apex of the pyramid will be positioned that far away from the geometric centre of the face in the direction of its surface normal.

This method differs from the Conway Polyhedron Notation version in that the inset and offset distances are given in model units rather than as a fraction of shape radius.

Parameters:
Name Type Argument Description
sides number <optional>

The number of sides as face must have to be affected, defaults to 0.

inset number <optional>

An inset distance from each edge in model units, defaults to 0 (no inset).

offset number <optional>

An optional distance from face surface in model units, defaults to 0 (no offset).

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

makeDefaultShape()

Makes this shape a 4-sided unit tetrahedron as the default shape for empty shapes.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape

meta( [sides])

The Conway meta operation is basically the join of a triakis operation.

If the sides argument is less than 3, all faces in the shape will be bevelled. If 3 or more, only those faces with a matching number of sides will be bevelled.

Parameters:
Name Type Argument Description
sides number <optional>

The number of sides as face must have to be affected, defaults to 0.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

noiseXY( [amplitude] [, scale] [, offset])

The noiseXY operation applies some X and Y axis spatial variation to each vertex in the shape based on the amplitude, scale and offset values.

The amplitude, scale and offset values are all applied to the Perlin noise function when it is run for each vertex. You can specify the scale and offset as either [x,y,z] vector arrays to control the variation in each axis, or as single numbers which will be applied equally to all axis.

This method differs from the Conway Polyhedron Notation version in that the amplitude, scale and offset distances are all given in model units rather than as a fraction of shape radius.

To have a noticeable effect, the amplitude and scale values cannot be too small relative to the shape size, so you will typically need to experiment a bit with this.

Parameters:
Name Type Argument Description
amplitude number <optional>

Effectively the magnitude of the spatial variation in model units, defaults to 250mm.

scale number | Array.<number> <optional>

A scale factor or [sx,sy,sz] vector array in model units, defaults to 1000mm (1m).

offset number | Array.<number> <optional>

A phase offset as a number or [dx,dy,dz] vector array in model units, defaults to 0 (no offset).

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const shape = PD.Shape.cylinder(72, 2000, 5000, 36);
shape.noiseXY(5000, 3000, 5000).setRadiusXY(6000);
CAD.add(shape);

normals()

Computes a list of face normal vectors.

The normal vector of each face is returned as an [x,y,z] vector array of unit length (normalized) defining its spatial direction in each major axis.

The order and index of normals in the returned list match the order and index of corresponding faces in the faces list.

Returns:

Return an array of face normals.

Type
Array.<Array.<number>>
Example
const distance = 250;
const face_normals = shape.normals();
for (let ii = 0; ii < shape.faces.length; ++ii) {
    for (const index of shape.faces[ii]) {
        hull_vertices.push(
            PD.VectorArray.translateInVectorDirection([], shape.vertices[index], face_normals[ii], distance)
        );
    }
}

offset(distance [, detail])

Modifies the shape by expanding all facets in the direction of their surface normals by the given distance, but maintaining their exact shape and surface area.

This process moves existing faces outwards and adds additional faces to cover the now open gaps and seams between them. The benefit of this method is that you can offset any convex shape by any positive amount, even many thousands of times its radius, and still have a valid shape shape.

Unfortunately this isn't true of concave shapes or when the distance value is negative. In these cases, maintaining the shape and area of facets isn't possible as they simply have to shrink in order to fit. As a result, this method will redirect to the PD.Shape#expand method when the given distance is less than zero.

Parameters:
Name Type Argument Description
distance number

The explosion distance as a positive value, defaults to 0 (no change).

detail number <optional>

The geometric detail at each corner (0 to 2), defaults to 2.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

offsetHull(distance [, detail])

Modifies the shape by generating a convex hull offsetting all vertices, edges and facets by their surface normals, but maintaining the exact shape and surface area of each facet.

This process modifies this shape by creating new vertex positions for all faces, but they will be the same size and orientation, just offset by the given distance. It also adds additional vertices and faces to fill in the seams and gaps between the exploded faces.

Parameters:
Name Type Argument Description
distance number

The explosion distance, defaults to 0.

detail number <optional>

The geometric detail at each corner (0 to 32), defaults to 1.

Returns:

Returns this modified shape.

Type
PD.Shape

openEdgeLoops()

Collects all edges that are not shared by two faces and assembles them into an array of one or more loops.

This method relies on all coincident edges sharing the same vertices, which means that the shape cannot have 'T' junctions where two faces meet somewhere along the edge of another face where it doesn't have a vertex. If you are not absolutely sure of the inter-connection state of your shape, call the PD.Shape#weld method first.

The loops generated by this method will likely be closed but not be planar. If the shape is more like an open surface, you should end up with one big outer boundary loop. If the shape is mostly closed, but has some holes within it, you should end up with loops for each hole.

You will need to work out how best to close a shape if you find that it has open edges.

The vertex indexes in the edges array are ordered such that the lowest ordinal index always comes first (array[0]) followed by the highest ordinal (array[1]).

Returns:

Returns an array of open edge loops.

Type
Array.<Array.<number>>
Example
/// Collect open edges and fill in top and bottom holes.
const super_shape = PD.Shape.superFormula({ innerRadius: 0.5, unfoldZ: 0.125 });
super_shape.scale(500).setRadiusXY(5000).weld();
const open_edges = super_shape.openEdgeLoops();
for (const loop of open_edges) {
    super_shape.faces.push(loop);
}

CAD.add(super_shape);

ortho()

The Conway ortho operation is effectively a double join operation.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

perlinNoise( [amplitude] [, scale] [, offset])

The Perlin noise operation applies some spatial variation to each vertex in the shape based on the amplitude, scale and offset values.

The amplitude, scale and offset values are all applied to the Perlin noise function when it is run for each vertex. You can specify the scale and offset as either [x,y,z] vector arrays to control the variation in each axis, or as single numbers which will be applied equally to all axis.

This method differs from the Conway Polyhedron Notation version in that the amplitude, scale and offset distances are all given in model units rather than as a fraction of shape radius.

To have a noticeable effect, the amplitude and scale values cannot be too small relative to the shape size, so you will typically need to experiment a bit with this.

Parameters:
Name Type Argument Description
amplitude number <optional>

Effectively the magnitude of the spatial variation in model units, defaults to 250mm.

scale number | Array.<number> <optional>

A scale factor or [sx,sy,sz] vector array in model units, defaults to 1000mm (1m).

offset number | Array.<number> <optional>

A phase offset as a number or [dx,dy,dz] vector array in model units, defaults to 0 (no offset).

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const shape = PD.Shape.cylinder(72, 2000, 5000, 36);
shape.perlinNoise(5000, 3000, 5000).setRadiusXY(6000);
CAD.add(shape);

propellor( [fraction])

The Conway propellor extended operation creates new skewed faces by making new points along each edge, 1/3rd the distance from v1- > v2, then connecting these into a new inset face. This breaks any rotational symmetry about the faces.

Parameters:
Name Type Argument Description
fraction number <optional>

The face rotation fraction (0.001 to 0.999), defaults to 1/3.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const shape = PD.Shape.anticupola(9).scale(9000);
shape.propellor();
CAD.add(shape);

reverse()

Reverses the orientation of all faces in the shape.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape

rotate(origin, axis, angle)

Rotates the shape around the given origin/axis by the given angle.

The origin is effectively the point about which the rotation should take place. It is subtracted from each point prior to the rotation, then added back afterwards.

Parameters:
Name Type Description
origin Array.<number>

The [x,y,z] vector array defining the origin point to rotate about.

axis Array.<number>

The [x,y,z] vector array defining the axial vector to rotate around.

angle number

The angle of rotation, in radians.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

scale(scale)

Applies a scaling factor to this shape.

Parameters:
Name Type Description
scale number | Array.<number>

A scale factor or [sx,sy,sz] vector array to multiple vertices by.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

scaleByAxis(axis, from, to, scale [, easing])

Scales the shape in the other two axis by an amount that varies over a range within the given axis.

If the from and to values are both in the range 0 to 1, then they are considered to be fractions of the size of the shape in the given axis. If either value is outside the range 0 to 1, then they are both considered to be in absolute model units along the axis.

You can use the PD.Shape#extents method if you want to find out the size range of your specific shape in each axis.

If the scale is given as a single number, it represents the maximum scale at the to point on the axis, varying from 1 at the from point. If given as a [fromScale, toScale] array, you can specify the scales to use at both the from and to points. You can specify an easing function if you wish to make it a non-linear variation.

If you choose the Z axis, then the varying scale will be applied to the X and Y components of each vertex in the shape. If you choose the X axis the scale will be applied in Y and Z, and for the Y axis, it will be applied in X and Z.

If you wish to scale vertexes in a non-Cartesian axis or about a point other than the origin, use the PD.AxisArray#scalePointsInXY method instead.

Parameters:
Name Type Argument Description
axis number

The axis to scale in (0:X, 1:Y or 2:Z).

from number

A value on the given axis to start scaling from ,in model units.

to number

A value on the given axis to finish scaling at, in model units.

scale number | Array.<number>

The scale at or above the to value, or a [fromScale,toScale] array, defaults to 1 (no scale).

easing function <optional>

An easing function to use, defaults to PD.Easing.linear.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
/// Scale cylinder with 12 sides and 20 segments.
const shape = PD.Shape.cylinder(12, 2000, 5000, 10);
shape.scaleByAxis(2, 0, 1, 2.0, PD.Easing.inOutQuint);
CAD.add(shape);

const frame = PD.Shape.frame(shape, 25, 50);
CAD.add(frame);

setColor(color)

Assigns a single color to all faces of the shape.

This method is a convenience method for setting the colors array to a single color value.

NOTE: This method overwrites any existing data in the colors array.

Parameters:
Name Type Description
color Array.<number>

The color to assign all faces, as an [r,g,b] array.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape

setHeight( [height])

Rescales all vertices so that the maximum range of the shape in the Z axis is equal to the given height.

NOTE: This method assumes that the shape is centred at the origin.

Parameters:
Name Type Argument Description
height number <optional>

The height to normalise shape to, defaults to 1.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
const super_shape = PD.Shape.superFormula();
super_shape.setHeight(2500).setRadiusXY(3500);
CAD.add(super_shape);

setRadius( [radius])

Rescales all vertices so that the maximum radius of the shape from the origin in all axis is equal to the given radius.

If you want to set the size based on the actual extents of the shape, use the PD.Shape#setRadius method instead.

NOTE: This method assumes that the shape is centred at the origin.

Parameters:
Name Type Argument Description
radius number <optional>

The radius to normalise shape to, defaults to 1.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.bevel(poly).setRadius(3440));
CAD.add(poly);

setRadiusXY( [radius] [, height])

Rescales all vertices so that the maximum radius of the shape in the X and Y axis is equal to the given radius.

If you provide the optional height argument, the height of the shape in the Z axis will be normalised to that too,

NOTE: This method assumes that the shape is centred at the origin.

Parameters:
Name Type Argument Description
radius number <optional>

The radius to normalise shape to, defaults to 1.

height number <optional>

The height to normalise shape to, defaults to 1.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
const super_shape = PD.Shape.superFormula();
super_shape.setHeight(2500).setRadiusXY(3500);
CAD.add(super_shape);

setSize( [sizeX] [, sizeY] [, sizeZ])

Rescales all vertices so that the dimensions of the shape's bounding box in each of the X, Y and Z axis is as given.

This method differs from PD.Shape#setRadius in that it is based on the bounding box (extents) of the shape rather than the distance of vertices from its centre.

Parameters:
Name Type Argument Description
sizeX number <optional>

The width of the shape in the X-axis, defaults to 1.

sizeY number <optional>

The depth of the shape in the Y-axis, defaults to width.

sizeZ number <optional>

The height of the shape in the X-axis, defaults to width.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
const super_shape = PD.Shape.superFormula();
super_shape.setSize(5000, 5000, 3500);
CAD.add(super_shape);

snub()

The Conway snub operation creates a new shape which is basically a PD.Shape.gyro operation performed on the dual of the shape. It creates a new face for each vertex, which is then twisted slightly and two new triangular faces added to replace each edges and fill the gaps.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const shape = new PD.Polyhedron('D12:S5000');
CAD.add(shape.clone().snub().scale(1.2835));
CAD.add(shape);

stretchByAxis(axis, from, to [, scale] [, easing])

Stretches the vertices of shape over a range in the given axis.

If the from and to values are both in the range 0 to 1, then they are considered to be fractions of the size of the shape in the given axis. If either value is outside the range 0 to 1, then they are both considered to be in absolute model units along the axis.

You can use the PD.Shape#extents method if you want to find out the size range of your specific shape in each axis.

Parameters:
Name Type Argument Description
axis number

The X, Y or Z axis to use (0:X, 1:Y, 2:Z).

from number

A value on the given axis to start stretching from in model units.

to number

A value on the given axis to finish stretching at in model units.

scale number <optional>

The amount to scale the axis range area by, defaults to 1 (no scale).

easing function <optional>

An easing function to use, defaults to PD.Easing.linear.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Examples
/// Stretch cylinder with 12 sides and 20 segments.
const shape = PD.Shape.cylinder(12, 2000, 2500, 10);
shape.stretchByAxis(2, 0.25, 1.0, 2.0, PD.Easing.inOutCubic);
CAD.add(shape);

const frame = PD.Shape.frame(shape, 25, 50);
CAD.add(frame);
/// Stretch cylinder with 24 sides and 10 segments.
const shape = PD.Shape.cylinder(24, 2000, 2500, 10);
shape.stretchByAxis(0, 0, 1, 4.0, PD.Easing.inOutQuint);
shape.stretchByAxis(2, 0, 1, 2.0, PD.Easing.outCubic);
shape.meta().cutAt(1700, 1).cutAt(7000, -1).translate([ 0, 0, -1700 ]);
CAD.add(shape);

const frame = PD.Shape.frame(shape, 25, 25).expand().ambo().join();
CAD.add(frame);

toJSON( [data])

Converts the object instance to a simple POJO for JSON storage.

This method is used to copy, store and save the data for ths object, so the returned object must have all the properties required be able to rebuild this instance in its entirety when passed to the class constructor.

NOTE: As vertexes are simple [x,y,z] vector arrays and each face is just an array of ordinal vertex indexes, both the faces and vertices arrays are used directly by the JSON object rather than being copied. This makes converting shapes to JSON very fast and efficient, which is important as this class is used quite a lot for data exchange. If you want to deep copy the data arrays, see the example code below:

Parameters:
Name Type Argument Description
data object <optional>

An optional parent object to append this data to.

Returns:

Returns a JSON object.

Type
object
Example
const shallow_copy = shape.toJSON();
const deep_copy = shape.clone().toJSON();

translate(offset)

Applies a [dx,dy,dz] translation to this shape.

Parameters:
Name Type Description
offset Array.<number>

A [x,y,z] vector array to move by.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

triakis( [sides] [, offset])

The Conway triakis operation divides specified faces into triangles to form a pyramid with its apex at the center of the face.

If the sides argument is less than 3, all faces in the shape will be divided. If 3 or more, only those faces with a matching number of sides will be divided.

If an offset value is given, then the apex of the pyramid will be positioned that far away from the geometric centre of the face in the direction of its surface normal.

This method differs from the Conway Polyhedron Notation version in that the offset distance is given in model units rather than as a fraction of shape radius.

Parameters:
Name Type Argument Description
sides Array.<number> | number <optional>

An array or face indexes or the number of sides a face must have to be affected, defaults to 0.

offset number <optional>

The distance of the pyramid apex away from the face center in model units, defaults to 0.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
/// Cupola-based space frame.
const poly = PD.Shape.cupola(9).scale(12000);
poly.join().expand().triakis(9, 2000).join();
poly.translate([ 0, 0, -6700 ]).scale([ 1, 1, 3 ]).cutAt(0, 1);
const frame = PD.Shape.frame(poly, 250, 150);
CAD.add(frame);

triangulate( [sides])

The triangulate operation divides specified faces into a triangular fan centered at the first vertex.

If the sides argument is less than 3, all faces in the shape will be divided. If 3 or more, only those faces with a matching number of sides will be divided.

To produce a useable result, this method requires that each face be convex in shape as dividing a concave face this way will result in overlapping triangular faces.

Parameters:
Name Type Argument Description
sides number <optional>

The number of sides as face must have to be affected, defaults to 0.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

truncate( [sides])

The Conway truncate operation is a triakis operation performed of the dual of the original shape, then converted back to a dual.

If the sides argument is less than 3, all faces in the shape will be bevelled. If 3 or more, only those faces with a matching number of sides will be bevelled.

Parameters:
Name Type Argument Description
sides number <optional>

The number of sides as face must have to be affected, defaults to 0.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape

twistByAxis(axis, from, to, angle [, easing])

Rotates the shape in the other two axis by an angle that varies over a range within the given axis.

If the from and to values are both in the range 0 to 1, then they are considered to be fractions of the size of the shape in the given axis. If either value is outside the range 0 to 1, then they are both considered to be in absolute model units along the axis.

You can use the PD.Shape#extents method if you want to find out the size range of your specific shape in each axis.

If the angle is given as a single number, it represents the maximum twist angle at the to point on the axis, varying from 0 at the from point. If given as a [fromAngle, toAngle] array, you can specify the angles to use at both the from and to points. You can specify an easing function if you wish to make it a non-linear variation.

If you choose the Z axis, then the twist will be applied to the X and Y components of each vertex in the shape. If you choose the X axis the twist will be applied in Y and Z, and for the Y axis, it will be applied in X and Z.

If you wish to scale vertexes in a non-Cartesian axis or about a point other than the origin, use the PD.AxisArray#twistPointsInXY method instead.

Parameters:
Name Type Argument Description
axis number

The axis to twist in (0:X, 1:Y or 2:Z).

from number

A value on the given axis to start twisting from ,in model units.

to number

A value on the given axis to finish twisting at, in model units.

angle number | Array.<number>

The angle at or above the to value, or a [fromAngle,toAngle] array, defaults to 0 (no twist).

easing function <optional>

An easing function to use, defaults to PD.Easing.linear.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Examples
/// Twist cylinder with 12 sides and 20 segments.
const shape = PD.Shape.cylinder(12, 2000, 5000, 10);
shape.twistByAxis(2, 0.1, 0.95, Math.PI / 4, PD.Easing.inOutSine);
CAD.add(shape);

const frame = PD.Shape.frame(shape, 25, 50);
CAD.add(frame);
const shape = PD.Shape.dome(8, 6, 4000);
shape.extrudeBase(5000, 5).triakis(0, -100);
shape.twistByAxis(2, -5000, 4000, Math.PI / 3, PD.Easing.inOutSine);
CAD.add(shape);

const frame = PD.Shape.frame(shape).expand().join().join();
CAD.add(frame);

vertexNormals()

Computes the averaged surface normal for each vertex.

The normal vector of each vertex in the shape is returned as an [x,y,z] vector array of unit length (normalized) defining its spatial direction in each major axis. Vertex normals are calculated as the average of all the face normals from faces that contain that vertex.

The order and index of vertex normals in the returned list match the order and index of corresponding vertices in the vertices list.

To allow further processing, additional information is appended to each normal array. Assuming the vertex is shared by N faces, each normal array has the following form:

[ normalX, normalY, normalZ, N, faceIndex1, faceIndex2, ..., faceIndexN ]

Returns:

Returns an array of averages vertex normals.

Type
Array.<Array.<number>>
Example
const distance = 250;
const vertex_normals = shape.vertexNormals();
for (let ii = 0; ii < shape.vertices.length; ++ii) {
    hull_vertices.push(
        PD.VectorArray.translateInVectorDirection([], shape.vertices[ii], vertex_normals[ii], distance)
    );
}

weld( [decimals])

Iterates the shape to merge vertices that share the same positions and ensure that adjacent edges share the same vertices.

This also ensures that all faces are oriented outwards relative to the geometric centre of the shape.

Parameters:
Name Type Argument Description
decimals number <optional>

The number of decimal places when comparing millimeter coordinates, defaults to 1 (0.1mm).

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
const config = {
    params: [ 1, 4, 0, 0, 0, 0, 2, -3 ],
    innerRadius: 0.5,
    unfoldZ: 0.75
};

const half_shape = PD.Shape.sphericalHarmonics(config).scale(400);
half_shape.cutAt(0, 1).cutAt(4500, -1).weld().join().expand();
CAD.add(half_shape);

ambo(shape) <static>

The Conway ambo operation is essentially the truncation of a shape by marking the midpoints of all its edges and cutting its vertices at those points.

The best way to think of the ambo operator is as a topological 'tween' between a polyhedron and its dual polyhedron. Thus the ambo of a dual polyhedron is the same as the ambo of the original.

Parameters:
Name Type Description
shape PD.Shape

The shape to base the operation on.

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.ambo(poly));
CAD.add(poly);

anticupola(sides [, alpha] [, height] [, topRadius]) <static>

Generates an anticupola shape of unit radius.

Parameters:
Name Type Argument Description
sides number

The number of sides in the shape (3 to 1024), defaults to 4.

alpha number <optional>

An optional base spacing factor (-1 to 1), defaults to zero (0).

height number <optional>

The height of the cupola top, defaults to height required for regular sided polygons.

topRadius number <optional>

The fractional radius of the cupola top (0 to 1), defaults to 0.5.

Returns:

Returns a new shape.

Type
PD.Shape

antiprism(sides [, radius] [, height]) <static>

Generates an extruded antiprism of the given radius with n sides.

Parameters:
Name Type Argument Description
sides number

The number of sides in the shape (3+), defaults to 4.

radius number <optional>

The radius of the prism in model units, defaults to 1.

height number <optional>

The height of the prism in model units, defaults to side length for square sides.

Returns:

Returns a new shape.

Type
PD.Shape

bevel(shape [, sides] [, offset]) <static>

The Conway bevel operation truncates the shape at its edges and vertices, creating a new facet in place of each edge and of each vertex.

If the sides argument is less than 3, all faces in the shape will be bevelled. If 3 or more, only those faces with a matching number of sides will be bevelled.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to base the operation on.

sides Array.<number> | number <optional>

An optional array of face indexes or the number of sides a face must have to be affected, defaults to 0 (all faces).

offset number <optional>

The distance of the triakis apex away from the face center in model units, defaults to 0.

Returns:

Returns a new modified shape.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.bevel(poly).setRadius(3440));
CAD.add(poly);

bipyramid(sides [, radius] [, height] [, elongation]) <static>

Generates a bipyramid of unit radius with n sides.

Parameters:
Name Type Argument Description
sides number

The number of sides in the shape (3+), defaults to 4.

radius number <optional>

The radius of the bipyramid in model units, defaults to 1.

height number <optional>

The height of the bipyramid in model units, defaults to radius.

elongation number <optional>

An optional size for a prism between the two pyramids, defaults to zero.

Returns:

Returns a new shape.

Type
PD.Shape

checkForSidesArray(faces [, sides]) <static>

Checks whether the sides argument is given as an array of face indices or the number of sides

Parameters:
Name Type Argument Description
faces Array.<Array.<number>>

The list of faces in the shape.

sides Array.<number> | number <optional>

An optional array of face indexes or the number of sides a face must have to be affected, defaults to 0 (all faces).

Returns:

Returns a list of faces to process.

Type
Array.<Array.<number>>
Example
function processShape(shape, sides) {

    const facesToProcess = PD.Shape.checkForSidesArray(shape.faces, sides);

    sides = (Array.isArray(sides)) ? 0 : PD.Utils.toInteger(sides, 0);

    for (const face of facesToProcess) {
        if ((sides < 3) || (face.length == sides)) {
            processFace(face);
        }
    }

};

convexHull(points [, smoothing] [, detail]) <static>

Generate a convex hull around the given points.

This process creates a new shape that has faces that are the same size and orientation as the given shape, just offset by the given distance and with additional faces to fill in the seams and gaps between offset facets.

Parameters:
Name Type Argument Description
points Array.<Array.<number>> | number

An array of 3D [x,y,z] coordinates arrays or the number of random points to generate, defaults to 64.

smoothing number | Array.<number> <optional>

An edge smoothing radius or a [min,max] radius array in model units, defaults to 0.

detail number <optional>

The geodesic detail at each point when smoothing (0 to 32), defaults to 0.

Returns:

Returns a new shape hull.

Type
PD.Shape
Examples
/// Random hemispherical rock generator.
const points = PD.VectorArray.pointCloud_Random(64, 5000, true);
const rock = PD.Polyhedron.convexHull(points, [ -500, 2000 ], 4);
CAD.add(rock);
/// Rough gemstone generator.
/// PD.Utils.randomNumber(22783); // Use a specific seed.
const points = PD.VectorArray.pointCloud_Random(48, 5000, true);
const rock = PD.Shape.convexHull(points);
rock.perlinNoise(8000, 5000, 0).truncate();
CAD.add(rock);

cuboid(width [, depth] [, height] [, center]) <static>

Generates a rectilinear prism centered at the origin.

           (0,d,h)            (w,d,h)
             7-------------------6
         Z  /|                  /|
         | / |                 / |
         |/  |        (w,0,h) /  | Y
 (0,0,h) 4-------------------5   |/
         |   3---------------|---2 (w,d,0)
         |  /(0,d,0)         |  /
         | /                 | /
         |/                  |/
         0-------------------1 -- -- X
      (0,0,0)             (w,0,0)

              3---------2
              |  back   |
              |    3    |
              |         |
    3---------7---------6---------2
    |  left   |   top   |  right  |
    |    4    |    5    |    2    |
    |         |         |         |
    0---------4---------5---------1
              |  front  |
              |    1    |
              |         |
              0---------1
              | bottom  |
              |    0    |
              |         |
              3---------2
Parameters:
Name Type Argument Default Description
width number

The size of the cuboid in the X-axis, defaults to 1.

depth number <optional>

The size of the cuboid in the Y-axis, defaults to width.

height number <optional>

The size of the cuboid in the Z-axis, defaults to width.

center boolean <optional>
false

Whether or not the shape is centered at the origin rather than its minimum corner, defaults to false.

Returns:

Returns a new cuboid shape.

Type
PD.Shape

cupola(sides [, alpha] [, height] [, topRadius]) <static>

Generates a cupola shape of unit radius.

A cupola is a shape formed by joining two polygons, one (the base) with twice as many edges as the other, by an alternating band of isosceles triangles and rectangles.

The alpha argument can be used to bias either the triangles (>0) of the rectangles (<0).

By default, the height of the cupola is set so that the side triangles and rectangles are regular. You can change this by specifically setting the height argument. You can set it to null or undefined to use the default setting.

You can also adjust the radius of the top face using the radius argument. This defaults to 0.5, but you can also use 0 for a conical shape, 1 for a cylindrical shape, or greater than 1 for an inverted shape.

Parameters:
Name Type Argument Description
sides number

The number of sides in the shape (3 to 1024), defaults to 4.

alpha number <optional>

An optional base spacing factor (-1 to 1), defaults to zero (0).

height number <optional>

The fractional height of the cupola top, defaults to height required for regular sided polygons.

topRadius number <optional>

The fractional radius of the cupola top (0 to 1), defaults to 0.5.

Returns:

Returns a new shape.

Type
PD.Shape

cutAt(shape, plane, keep [, cutFaces]) <static>

Cuts the faces of the given shape by the given plane and either keeps all of them or just those in the front or rear of the plane.

To make this method easier to use, the directional component of any given plane equation does not need to be normalised as this will be done automatically. Thus, you could provide a plane array such as [ 1, 1, 1, -500 ] and it will be automatically converted to [ 0.5773503, 0.5773503, 0.5773503, -500 ].

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to base the cutting on.

plane number | Array.<number>

A height value in the Z axis or an [a,b,c,d] plane array to cut the shape at.

keep number

Which side(s) to retain (0:Both, 1:Front, -1:Rear), defaults to 0 (both).

cutFaces Array | number <optional>

An optional array in which to store any newly added cut faces. If given as a number instead of an array, it gives a distance by which a base is created by extruding cut surfaces in the opposite direction of the cutting plane.

Returns:

Returns a new shape cut from the given shape.

Type
PD.Shape
Example
const cut_faces = [];
const cut_plane = [ 0, 0, 1, 0 ];
const base_poly = new PD.Polyhedron('D8:th(0.15,0.025)ajeS9000');
const dome_with_holes = PD.Shape.cutAt(base_poly, cut_plane, 1, cut_faces).translate([ 0, 0, 3000 ]);
for (const face of cut_faces) {
    dome_with_holes.faceExtrude(face, -3000, cut_plane, 6);
}

CAD.add(dome_with_holes);

cylinder(sides [, radius] [, height] [, segments]) <static>

Generates a cylindrical prism of unit radius with n sides and segments.

Parameters:
Name Type Argument Description
sides number

The number of sides in the shape (3 to 1024), defaults to 4.

radius number <optional>

The radius of the shape in model units, defaults to 1.

height number <optional>

The height of the shape in model units, defaults to side length for square sides.

segments number <optional>

The number of vertical segments in the shape, defaults to 1.

Returns:

Returns a new polyhedron.

Type
PD.Shape
Examples
const cyl = PD.Shape.cylinder(36, 1000, 500);
CAD.add(cyl);
const segments = 12;

/// Create base shape to work on.
const cyl = PD.Shape.cylinder(segments, 1000, 500);

/// Create local coordinates.
const axis = new PD.AxisArray();
axis.moveOrigin(0, 2000, 0);
axis.rotateZ(Math.PI / 4);
cyl.applyAxis(axis);

/// Create different positive/negative scales.
const scale_positive = [3.50, 1.5, 1.0];
const scale_negative = [1.25, 1.5, 1.0];

/// Extract the bottom ring of vertices.
const base = cyl.vertices.slice(0, segments);

/// Apply both scales about the origin.
axis.scalePoints(base, scale_positive, scale_negative);
CAD.add(cyl);

dome( [latRings] [, lngRings] [, radius]) <static>

Generates a hemispheric shape from lat/lng points.

Parameters:
Name Type Argument Description
latRings number <optional>

The number of longitudinal divisions (1 to 178), defaults to 8.

lngRings number <optional>

The number of latitudinal divisions (3 to 360), defaults to 16.

radius number <optional>

The radius of the point distribution, defaults to 1.

Returns:

Returns a new hemispherical shape.

Type
PD.Shape
Example
/// Create a dome.
const shape1 = PD.Shape.dome(18, 9, 5000);
shape1.translate([ -1000, 0, 0 ]);

/// Create sphere.
const shape2 = PD.Shape.sphere(18, 9, 3000);
shape2.translate([ 1000, 0, 3500 ]);

/// Convert to CAD shapes.
const solid1 = CAD.addSolid(shape1);
const solid2 = CAD.addSolid(shape2);

CAD.translate(CAD.union([ solid1, solid2 ]), [ 0, -6000, 0 ]);
CAD.translate(CAD.subtract(solid1, solid2), [ 0, 6000, 0 ]);

domeFibonacci(num_pts [, radius]) <static>

Generates a hemispheric shape from a Fibonacci spiral.

The distribution of points is based in the Fibonacci spiral which gives a pretty good approximation of equally-spaced points on the surface pf a sphere.

Parameters:
Name Type Argument Description
num_pts number

The number of points to generate (4 to 2048), defaults to 48.

radius number <optional>

The radius of the dome, defaults to 1.

Returns:

Returns a new hemispherical shape.

Type
PD.Shape
Example
/// Create a dome from Fibonacci spiral.
const shape1 = PD.Shape.domeFibonacci(128, 5000);
shape1.translate([ -1000, 0, 0 ]);

/// Create geodesic sphere.
const shape2 = PD.Shape.sphereGeodesic(8, 3000);
shape2.translate([ 1000, 0, 3500 ]);

/// Convert to CAD shapes.
const solid1 = CAD.addSolid(shape1);
const solid2 = CAD.addSolid(shape2);

CAD.translate(CAD.union([ solid1, solid2 ]), [ 0, -6000, 0 ]);
CAD.translate(CAD.subtract(solid1, solid2), [ 0, 6000, 0 ]);

domeGeodesic( [detail] [, radius]) <static>

Generates a hemispheric shape from geodesic triangles.

This distribution is generated by progressively dividing into spherical triangles and then inflating the interpolated points to the radius of the sphere.

Parameters:
Name Type Argument Description
detail number <optional>

The level of triangulation (0 to 32), defaults to 6.

radius number <optional>

The radius of the point distribution, defaults to 1.

Returns:

Returns a new hemispherical shape.

Type
PD.Shape
Example
/// Create a geodesic dome.
const shape1 = PD.Shape.domeGeodesic(8);
shape1.scale(5000).translate([ -1000, 0, 0 ]);

/// Create sphere from Fibonacci spiral.
const shape2 = PD.Shape.sphereFibonacci(128);
shape2.scale(3500).translate([ 1000, 0, 3500 ]);

/// Convert to CAD shapes.
const solid1 = CAD.addSolid(shape1);
const solid2 = CAD.addSolid(shape2);

CAD.translate(CAD.union([ solid1, solid2 ]), [ 0, -6000, 0 ]);
CAD.translate(CAD.subtract(solid1, solid2), [ 0, 6000, 0 ]);

domeRandom( [num_pts] [, radius]) <static>

Generates a hemispheric shape from random points.

Parameters:
Name Type Argument Description
num_pts number <optional>

The number of points to generate (6 to 2048), defaults to 48.

radius number <optional>

The radius of the point distribution, defaults to 1.

Returns:

Returns a new hemispherical shape.

Type
PD.Shape
Example
/// PD.Utils.randomNumber(22783); // Use a specific seed.
const shape = PD.Shape.domeRandom(64, 5000);
CAD.add(shape);

dual(shape) <static>

The Conway dual operation creates a new shape in which the centroid of each face in the original shape becomes a new vertex in the dual, and each vertex in the original becomes the centroid of a new face.

Parameters:
Name Type Description
shape PD.Shape

The shape to base the operation on.

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.dual(poly));
CAD.add(poly);

expand(shape) <static>

The Conway expand operation is basically a double ambo operation, which is the truncation of a shape by marking the midpoints of all its edges and cutting its vertices at those points.

Parameters:
Name Type Description
shape PD.Shape

The shape to base the operation on.

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.expand(poly));
CAD.add(poly);

frame(shape [, inset] [, thickness] [, glazing]) <static>

Generates a structural frame by hollowing out the shape and creating a structural frame with bars running along each of its edges.

This process creates a new shape with bars of the given width and thickness along each edge.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to generate frame from.

inset number <optional>

The inset width of frame elements, defaults to 25mm.

thickness number <optional>

The frame thickness as a positive value, defaults to 50mm.

glazing boolean <optional>

Whether or not to generate glazing panes between frames.

Returns:

Returns a new framing shape.

Type
PD.Shape
Example
/// Cupola-based space frame.
const shape = PD.Shape.anticupola(9).scale(9000);
shape.triakis(9, 2000).expand().join().scale([1, 1, 3]);
shape.translate([ 0, 0, -7500 ]).cutAt(0, 1);
CAD.add(shape);

const frame = PD.Shape.frame(shape, 250, 150);
CAD.add(frame);

generateSection(shape, plane) <static>

Computes sectional contour(s) through the shape as cut by the given plane.

To make this method easier to use, the directional component of any given plane equation does not need to be normalised as this will be done automatically. Thus, you could provide a plane array such as [ 1, 1, 1, -500 ] and it will be automatically converted to [ 0.5773503, 0.5773503, 0.5773503, -500 ].

Parameters:
Name Type Description
shape PD.Shape

The shape to generate the section through.

plane number | Array.<number>

A [a,b,c,d] plane array or vertical height value in the Z axis to section the shape at.

Returns:

Returns a new shape with vertices and faces on the cutting plane, or null if no intersection.

Type
PD.Shape | null
Example
const poly = new PD.Polyhedron('D8:tk').scale(2000);

const section = PD.Shape.generateSection(poly, [ -1, -1, 4, -200 ]);
if (section?.faces) {

    /// Add as face(s).
    CAD.addShell(section);

    /// Add as wire(s).
    for (const face of section.faces) {
        const points = face.map(index => section.vertices[index]);
        CAD.addWire(points, true);
    }

}

/// Shrink polyhedron a bit.
CAD.add(poly.inflate(-100));

gyro(shape [, offset] [, fraction]) <static>

The Conway gyro operation creates a new shape in which a new face is created at each vertex of its dual, which is then twisted slightly and two new triangular faces added to replace each edges and fill the gaps.

NOTE: When using an offset value not equal to zero, this operation will often create non-planar faces. If that is detected, then the resulting faces will be automatically triangulated.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to base the operation on.

offset number <optional>

The distance of the center apex away from the face center in model units, defaults to 0.

fraction number <optional>

The face rotation fraction (0.001 to 0.999), defaults to 1/3.

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape
Example
const shape = PD.Shape.cuboid(5000);
CAD.add(PD.Shape.gyro(shape));

inflate(shape, distance [, checkPlanes]) <static>

Expand all vertices in the direction of their surface normals by the given distance.

Expansion is different from offsetting in that the given distance refers to the movement of each vertex rather than to each face. Vertices move in the direction of their average surface normals, which is effectively the normalised sum of each face normal that the vertex is shared by. Movement is outwards if the distance is positive or inwards if it is negative.

The result is a set of vertices that are exactly the given distance away from their original positions. Depending on the number of faces shared by each vertex, and their relative orientations, this may result in faces changing orientation slightly and not being parallel to their original position. In some rare cases it may even result in faces that are no longer planar.

If you want to specify the exact perturbation distance of faces rather than vertices use the PD.Shape#offset method instead.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to expand from.

distance number

The expansion distance, defaults to 0.

checkPlanes number <optional>

Extra checks (0:None, 1:AngleWeighted, 2:FirstPlane, 3:AllPlanes), defaults to 0.

Returns:

Returns this shape to support method chaining.

Type
PD.Shape
Example
const shape = PD.Shape.prism(9, 1500, 1000).ortho();
CAD.add(PD.Shape.inflate(shape, 200));
CAD.add(shape);

join(shape) <static>

The Conway join operation is basically an ambo operation performed on the dual of the original shape, then converted back to a dual.

Parameters:
Name Type Description
shape PD.Shape

The shape to base the operation on.

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape
Examples
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.join(poly).setRadius(3489));
CAD.add(poly);
/// Cupola-based space frame.
const poly = PD.Shape.cupola(9).scale(12000);
poly.join().expand().triakis(9, 2000).join();
poly.translate([ 0, 0, -6700 ]).scale([ 1, 1, 3 ]).cutAt(0, 1);
const frame = PD.Shape.frame(poly, 250, 150);
CAD.add(frame);

meta(shape [, sides]) <static>

The Conway meta operation is basically the join of a triakis operation.

If the sides argument is less than 3, all faces in the shape will be bevelled. If 3 or more, only those faces with a matching number of sides will be bevelled.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to base the operation on.

sides Array.<number> | number <optional>

An optional array of face indexes or the number of sides a face must have to be affected, defaults to 0 (all faces).

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.meta(poly).setRadius(3489));
CAD.add(poly);

metaballs( [config]) <static>

Generates an enclosed surface from one or more metaball blobs.

This method first creates a temporary 3D volumetric grid around the extents of all the given balls and computes a signed distance field within it. It then generates a 3D surface at the given threshold using either a Marching Cubes, Surface Nets or Voxelisation algorithm.

You can specify a minimum and/or maximum extends for the volumetric grid,

Parameters:
Name Type Argument Description
config object <optional>

A configuration object.

Properties of config:
Name Type Argument Description
balls Array.<Array.<number>> <optional>

An array of one or more [x,y,z,radius] ball definitions.

cells number | Array.<number> <optional>

The number of grid cells in each axis or or a [cellsX,cellsY,cellsZ] array, defaults to 16.

type number <optional>

The type of surface (0:Triangular[MarchingCubes], 1:Polygonal[SurfaceNets], 2:Voxelised), defaults to 0.

min Array.<number> <optional>

The [x,y,z] coordinate array of the minimum extents in each axis.

max Array.<number> <optional>

The [x,y,z] coordinate array of the maximum extents in each axis.

expansion number <optional>

A fraction of the cell size to expand the calculated extents by (0 to 1), defaults to 0.5.

threshold number <optional>

The value to generate the iso-surface at, defaults to 0.

Returns:

Returns a new shape with the blob surfaces.

Type
PD.Shape
Example
const blob = PD.Shape.metaballs({
    type: 1,
    balls: [
        [     0,     0,     0, 3000.0 ],
        [  2000,     0,  2500, 2000.0 ],
        [     0, -2000,  2000, 1500.0 ]
    ]
});

/// Convert to a OCC solid.
const inside = CAD.addSolid(blob);

// Expand the surface by 150mm and cut the top off.
const outside = CAD.addSolid(blob.inflate(150).cutAt(2500, -1));

/// Subtract the insides out.
CAD.subtract(outside, inside);

newInstance( [vertices] [, faces] [, name]) <static>

This is used to allow subclasses to create instance of their own class when using static generators.

Parameters:
Name Type Argument Description
vertices Array.<Array.<number>> <optional>

An array of [x,y,z] vertex coordinates.

faces Array.<Array.<number>> <optional>

An array of face boundary arrays, each containing three or more vertex indices.

name string <optional>

A human-readable name for the shape.

Returns:

Returns a new shape.

Type
PD.Shape

offset(shape, distance [, detail] [, useAbsoluteSteps]) <static>

Expand all facets in the direction of their surface normals by the given distance, but maintaining their exact shape and planar area.

This process creates a new shape which copies all faces in the given shape, moves them outwards and adds additional faces to cover the now open seams and gaps between them. The benefit of this method is that you can offset any convex shape by any positive amount, even by many thousands of times its radius, and still have a valid shape.

Unfortunately this isn't true of concave shapes or when the distance value is negative. In these cases, maintaining the shape and area of facets isn't possible as they simply have to shrink in order to fit. As a result, this method will redirect to the PD.Shape.expand method when the given distance is less than zero. When working with concave shapes, you are just going to have to experiment.

Parameters:
Name Type Argument Default Description
shape PD.Shape

The shape to offset from.

distance number

The face offset distance as a positive value, defaults to 0 (no change).

detail number <optional>

The geometric detail at each corner (-1 to 32), defaults to 2.

useAbsoluteSteps boolean <optional>
false

When true, the offset uses detail as the absolute number of subdivisions regardless of spherical angle, defaults to false.

Returns:

Returns a new shape if the distance is non-zero, or the given shape.

Type
PD.Shape
Example
const offset = 500;
const spacing = 4000;
const shape = PD.Shape.cuboid(1000, 1500, 1000);
CAD.add(PD.Shape.offset(shape, offset, -1).translate([ -spacing, -spacing, 0 ]));
CAD.add(PD.Shape.offset(shape, offset,  0).translate([ -spacing,        0, 0 ]));
CAD.add(PD.Shape.offset(shape, offset,  1).translate([ -spacing,  spacing, 0 ]));
CAD.add(PD.Shape.offset(shape, offset,  2).translate([        0,  spacing, 0 ]));
CAD.add(PD.Shape.offset(shape, offset,  3).translate([  spacing,  spacing, 0 ]));
CAD.add(PD.Shape.offset(shape, offset,  8).translate([  spacing,        0, 0 ]));
CAD.add(PD.Shape.offset(shape, offset, 16).translate([  spacing, -spacing, 0 ]));
CAD.translate(CAD.offset(CAD.addSolid(shape), offset), [      0, -spacing, 0 ]);
CAD.add(shape);

offsetHull(shape, distance [, detail]) <static>

Generate a convex hull by offsetting all vertices, facets and edges in the a shape by their surface normals, but maintaining the exact shape and planar area of each facet in the original.

This process creates a new shape that has faces that are the same size and orientation as the given shape, just offset by the given distance and with additional faces to fill in the seams and gaps between offset facets.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to offset from.

distance number

The explosion distance, defaults to 0.

detail number <optional>

The geodesic detail at each corner (1 to 32), defaults to 1.

Returns:

Returns a new exploded shape.

Type
PD.Shape
Example
const offset = 500;
const spacing = 4000;
const shape = PD.Shape.cuboid(1000, 1500, 1000);
CAD.add(PD.Shape.offsetHull(shape, offset, -1).translate([ -spacing, -spacing, 0 ]));
CAD.add(PD.Shape.offsetHull(shape, offset,  0).translate([ -spacing,        0, 0 ]));
CAD.add(PD.Shape.offsetHull(shape, offset,  1).translate([ -spacing,  spacing, 0 ]));
CAD.add(PD.Shape.offsetHull(shape, offset,  2).translate([        0,  spacing, 0 ]));
CAD.add(PD.Shape.offsetHull(shape, offset,  3).translate([  spacing,  spacing, 0 ]));
CAD.add(PD.Shape.offsetHull(shape, offset,  8).translate([  spacing,        0, 0 ]));
CAD.add(PD.Shape.offsetHull(shape, offset, 16).translate([  spacing, -spacing, 0 ]));
CAD.translate(CAD.addHull(PD.Shape.offsetHull(shape, offset,  6).vertices), [0, -spacing, 0 ]);
CAD.add(shape);

ortho(shape) <static>

The Conway ortho operation is effectively a double join operation.

Parameters:
Name Type Description
shape PD.Shape

The shape to base the operation on.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.ortho(poly).setRadius(3489));
CAD.add(poly);

prism(sides [, radius] [, height]) <static>

Generates an extruded prism of unit radius with n sides.

Parameters:
Name Type Argument Description
sides number

The number of sides in the shape (3+), defaults to 4.

radius number <optional>

The radius of the prism in model units, defaults to 1.

height number <optional>

The height of the prism in model units, defaults to side length for square sides.

Returns:

Returns a new shape.

Type
PD.Shape

propellor(shape [, fraction]) <static>

The Conway propellor extended operation creates new skewed faces by making new points along each edge, 1/3rd the distance from v1- > v2, then connecting these into a new inset face. This breaks any rotational symmetry about the faces.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to base the operation on.

fraction number <optional>

The face rotation fraction (0.001 to 0.999), defaults to 1/3.

Returns:

Returns this modified shape to support method chaining.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.propellor(poly).setRadius(3489));
CAD.add(poly);

pyramid(sides [, radius] [, height] [, segments]) <static>

Generates a pointed polyhedron of unit radius with n triangular sides.

Parameters:
Name Type Argument Description
sides number

The number of sides in the pyramid (3 to 1024), defaults to 4.

radius number <optional>

The radius of the pyramid in model units, defaults to 1.

height number <optional>

The height of the pyramid in model units, defaults to radius.

segments number <optional>

The number of vertical segments in the shape, defaults to 1.

Returns:

Returns a new polyhedron.

Type
PD.Shape
Example
const shape = PD.Shape.pyramid(9, 6000, 12000);
shape.frame(150, 150);
CAD.add(shape);

rotunda(side [, radius] [, height]) <static>

Generates a pentagonal rotunda of unit radius.

As this shape always has 10 sides in its base, the sides value is ignored, but retained for comparability with other spherical generator methods.

Parameters:
Name Type Argument Description
side number

This argument is there for compatibility with other generators, but is ignored.

radius number <optional>

The radius of the shape in model units, defaults to 1.

height number <optional>

The height of the shape in model units, defaults to (radius * 0.850650808).

Returns:

Returns a new shape.

Type
PD.Shape

sliceAt(shape, plane) <static>

Slices a shape into two new shapes by cutting it with the given plane.

This method returns an array of two shapes, the first being created from those faces in front of the plane and the second from those behind. If the plane does not actually intersect the given shape, one of the two will be empty.

Defining a Plane

This method uses an infinite plane to cut the shape, defined by an [a,b,c,d] plane array based on the Ax + Bx + Cz + D = 0 equation for a 3D plane. This means providing an array with four numbers that define the A, B, C and D components of the equation.

Alternatively, if you just want to cut a shape using a horizontal plane, you can pass a single number rather than a plane array. This number is used as the height on the Z axis of a cutting plane that faces towards the +Z axis.

The first three values in the plane array define its normal direction, which also defines the front and rear sides of the plane. Anything on the same side as the normal is pointing is in front, and anything on the other side is behind.

To make this method easier to use, the directional component of any given plane array does not need to be normalised as this will be done automatically. Thus, you could provide a plane array such as [ 1, 1, 1, -500 ] and it will be automatically normalized to [ 0.5773503, 0.5773503, 0.5773503, -500 ].

NOTE: When providing just a single number instead of a plane, it is important to remember that the number represents the plane height rather than the D component. Thus, a numeric value of 250 is equivalent to specifying [0,0,1,-250] as the plane array.

Parameters:
Name Type Description
shape PD.Shape

The shape to base the slicing on.

plane number | Array.<number>

A height value in the Z axis or an [a,b,c,d] plane array to cut the shape at.

Returns:

Returns an array iof two new shapes sliced from the given shape.

Type
Array.<PD.Shape>
Example
/// Slice cylinder into two separate halves.
const shape = PD.Shape.cylinder(12, 2000, 5000);
const [ top, bot ] = PD.Shape.sliceAt(shape, [ 1, 1, 4, -2500 ]);
CAD.add(top.translate([ 0, 0, 500 ]));
CAD.add(bot);

sliceUp(shape, plane [, slices] [, increment]) <static>

Slice a shape up into a set of new shapes by cutting it into multiple segments using the given plane.

This method returns an array of shapes created by successively slicing the given base shape the given number of times by moving the cutting plane incrementally in its normal direction.

Defining a Plane

This method uses an infinite plane to cut the shape, defined by an [a,b,c,d] plane array based on the Ax + Bx + Cz + D = 0 equation for a 3D plane. This means providing an array with four numbers that define the A, B, C and D components of the equation.

Alternatively, if you just want to cut a shape using a horizontal plane, you can pass a single number rather than a plane array. This number is used as the height on the Z axis of a cutting plane that faces towards the +Z axis.

The first three values in the plane array define its normal direction, which also defines the front and rear sides of the plane. Anything on the same side as the normal is pointing is in front, and anything on the other side is behind.

To make this method easier to use, the directional component of any given plane array does not need to be normalised as this will be done automatically. Thus, you could provide a plane array such as [ 1, 1, 1, -500 ] and it will be automatically normalized to [ 0.5773503, 0.5773503, 0.5773503, -500 ].

NOTE: When providing just a single number instead of a plane, it is important to remember that the number represents the plane height rather than the D component. Thus, a numeric value of 250 in the Z axis is equivalent to specifying [0,0,1,-250] as the plane array.

Defining Slices

It is important to point out here that 'slice' can be used as both an adjective and a noun, which will likely cause some initial confusion when using this modifier. If you slice a cake once, you end up wth two slices. If you slice it twice radially across its diameter, you end up with 4 slices. If you do two parallel slices across it, you end up with three slices.

To avoid all such issues, when used in this context, the terms 'slice' and slices refer to the number of cuts made rather than the number of chunks that might result.

Also, slicing up shapes is complex, so a modifier like this needs to be quite flexible in its specification of where each slice is taken.

The simplest way to slice up a shape is to give just the plane equation and the number of slices to take. In this case, this method will compute the near and far extents of the shape in the line of the plane and generate the given number of uniform slices over its extents.

If slices is given as an array, each value in the array is taken as an absolute offset from the given plane at which to take a slice. In this case, the values will be sorted in ascending order and the incrementvalue ignored. Again, offset values are given as distances in in the direction of the surface normal of the plane, not as the D value of the plane equation. Thus, to cut three slices, the first being 3m, then 2m and 1, use [3000,5000,6000].

If you wish to specify increments for each slice instead of absolute offsets, include the number of slices you want and then use an array of increments for each slice as the increment argument. Thus, to cut three slices, the first being 3m, then 2m and 1, use [3000,2000,1000]. If there are less values in the array than there are slices, the last increment is simply repeated. If there are more values in the array than there are slices, only the number of slices are used. An invalid array will end up cutting at just the plane.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to base the slicing on.

plane number | Array.<number>

A height value in the Z axis or an [a,b,c,d] plane array to cut the shape at.

slices number | Array.<number> <optional>

The number of slices to cut through the shape (1 to 1024) or an array of slice distances, defaults to 1.

increment number <optional>

The distance to move the plane on each slice, defaults to extents() / (slices + 1).

Returns:

Returns an array of new shapes as slices of the given shape.

Type
Array.<PD.Shape>
Examples
/// Cut cylinder using 4 slices.
const shape = PD.Shape.cylinder(12, 2000, 5000);
const slices = PD.Shape.sliceUp(shape, [ 1, 1, 4, -900 ], 4, 1000);

let z = 0;
for (const slice of slices) {
    CAD.add(slice.translate([ 0, 0, z ]));
    z += 500;
}
/// Cut cylinder using 3 absolute slices.
const shape = PD.Shape.cylinder(12, 2000, 5000);
const slices = PD.Shape.sliceUp(shape, [ 1, 1, 4, -900 ], [ 800, 1800, 2400 ]);

let z = 0;
for (const slice of slices) {
    CAD.add(slice.translate([ 0, 0, z ]));
    z += 500;
}
/// Cut cylinder using 3 relative slices.
const shape = PD.Shape.cylinder(12, 2000, 5000);
const slices = PD.Shape.sliceUp(shape, [ 1, 1, 4, -900 ], 3, [ 800, 1000, 600 ]);

let z = 0;
for (const slice of slices) {
    CAD.add(slice.translate([ 0, 0, z ]));
    z += 500;
}

snub(shape) <static>

The Conway snub operation creates a new shape which is basically a PD.Shape.gyro operation performed on the dual of the shape. It creates a new face for each vertex, which is then twisted slightly and two new triangular faces added to replace each edges and fill the gaps.

Parameters:
Name Type Description
shape PD.Shape

The shape to base the operation on.

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape
Example
const shape = new PD.Polyhedron('D12:S5000');
CAD.add(PD.Polyhedron.snub(shape).scale(1.28225));
CAD.add(shape);

sortPointsAntiClockwise(center, points) <static>

This method is used to order the offset points of each face around a vertex so that it can join them up into a triangle or quad.

            3        |            1
    0       +   2    |    2       +   0
    +           +    |    +           +
       center        |        center
          +          |           +
                 4   |                 4
     1           +   |     3           +
     +               |     +
        BEFORE       |         AFTER
Parameters:
Name Type Description
center Array.<number>

The [x,y,z] coordinate array of a central point.

points Array.<Array.<number>>

An array of [x,y,z] coordinate arrays defining points around the center.

Returns:

Returns an array with the given points sorted anti-clockwise around center.

Type
Array.<Array.<number>>

sphere( [latRings] [, lngRings] [, radius]) <static>

Generates a spherical shape from lat/lng points.

Parameters:
Name Type Argument Description
latRings number <optional>

The number of longitudinal divisions (1 to 178), defaults to 8.

lngRings number <optional>

The number of latitudinal divisions (3 to 360), defaults to 16.

radius number <optional>

The radius of the point distribution, defaults to 1.

Returns:

Returns a new spherical shape.

Type
PD.Shape
Example
/// Create a dome.
const shape1 = PD.Shape.dome(18, 9, 5000);
shape1.translate([ -1000, 0, 0 ]);

/// Create sphere.
const shape2 = PD.Shape.sphere(18, 9, 3000);
shape2.translate([ 1000, 0, 3500 ]);

/// Convert to CAD shapes.
const solid1 = CAD.addSolid(shape1);
const solid2 = CAD.addSolid(shape2);

CAD.translate(CAD.union([ solid1, solid2 ]), [ 0, -6000, 0 ]);
CAD.translate(CAD.subtract(solid1, solid2), [ 0, 6000, 0 ]);

sphereDelaunay(points [, radius]) <static>

Uses Delaunay triangulation to generate a shape from a series of [azi,alt] polar points.

Parameters:
Name Type Argument Description
points Array.<Array.<number>> | number

An array of 2D [azi,alt] polar coordinates or the number of random points to generate, defaults to 64.

radius number <optional>

The radius of the point distribution, defaults to 1000.

Returns:

Returns a new shape.

Type
PD.Shape
Example
/// const points = PD.VectorArray.polarPoints_Random(64, true);
/// const points = PD.VectorArray.polarPoints_Geodesic(6, false);
const points = PD.VectorArray.polarPoints_Fibonacci(128, false);
const shape = PD.Polyhedron.sphereDelaunay(points, 5000).cutAt(0, 1);
shape.perlinNoise(5000, [ 5000, 5000, 0 ], 900);
CAD.add(shape.weld());

sphereFibonacci(num_pts [, radius]) <static>

Generates a spherical shape from a Fibonacci spiral.

The distribution of points is based in the Fibonacci spiral which gives a pretty good approximation of equally-spaced points on the surface of a sphere.

Parameters:
Name Type Argument Description
num_pts number

The number of points to generate (4 to 2048), defaults to 48.

radius number <optional>

The radius of the sphere, defaults to 1.

Returns:

Returns a new spherical shape.

Type
PD.Shape
Example
/// Create a geodesic dome.
const shape1 = PD.Shape.domeGeodesic(8);
shape1.scale(5000).translate([ -1000, 0, 0 ]);

/// Create sphere from Fibonacci spiral.
const shape2 = PD.Shape.sphereFibonacci(128);
shape2.scale(3500).translate([ 1000, 0, 3500 ]);

/// Convert to CAD shapes.
const solid1 = CAD.addSolid(shape1);
const solid2 = CAD.addSolid(shape2);

CAD.translate(CAD.union([ solid1, solid2 ]), [ 0, -6000, 0 ]);
CAD.translate(CAD.subtract(solid1, solid2), [ 0, 6000, 0 ]);

sphereGeodesic( [detail] [, radius]) <static>

Generates a spherical shape from geodesic triangles.

This distribution is generated by progressively dividing into spherical triangles and then inflating the interpolated points to the radius of the sphere.

Parameters:
Name Type Argument Description
detail number <optional>

The level of triangulation (0 to 32), defaults to 6.

radius number <optional>

The radius of the point distribution, defaults to 1.

Returns:

Returns a new spherical shape.

Type
PD.Shape
Example
/// Create a dome from Fibonacci spiral.
const shape1 = PD.Shape.domeFibonacci(128, 5000);
shape1.translate([ -1000, 0, 0 ]);

/// Create geodesic sphere.
const shape2 = PD.Shape.sphereGeodesic(8, 3000);
shape2.translate([ 1000, 0, 3500 ]);

/// Convert to CAD shapes.
const solid1 = CAD.addSolid(shape1);
const solid2 = CAD.addSolid(shape2);

CAD.translate(CAD.union([ solid1, solid2 ]), [ 0, -6000, 0 ]);
CAD.translate(CAD.subtract(solid1, solid2), [ 0, 6000, 0 ]);

sphereRandom( [num_pts] [, radius]) <static>

Generates a spherical shape from random points.

Parameters:
Name Type Argument Description
num_pts number <optional>

The number of points to generate (6 to 2048), defaults to 48.

radius number <optional>

The radius of the point distribution, defaults to 1.

Returns:

Returns a new spherical shape.

Type
PD.Shape
Example
/// PD.Utils.randomNumber(22783); // Use a specific seed.
const shape = PD.Shape.sphereRandom(128, 5000);
CAD.add(shape);

sphereVoronoi(points [, radius]) <static>

Uses Voronoi cellularisation to generate a shape from a series of [azi,alt] polar points.

Parameters:
Name Type Argument Description
points Array.<Array.<number>> | number

An array of 2D [azi,alt] polar coordinates or the number of random points to generate, defaults to 64.

radius number <optional>

The radius of the point distribution, defaults to 1000.

Returns:

Returns true if the triangulation succeeded, otherwise false.

Type
boolean
Example
/// const points = PD.VectorArray.polarPoints_Random(128, false);
/// const points = PD.VectorArray.polarPoints_Geodesic(6, false);
const points = PD.VectorArray.polarPoints_Fibonacci(128, false);
const shape = PD.Polyhedron.sphereVoronoi(points, 5000).cutAt(0, 1);
shape.perlinNoise(5000, [ 5000, 5000, 0 ], 900);
CAD.add(shape.weld());

sphericalHarmonics( [config] [, usedParams]) <static>

Generates a cylindrical surface of unit radius perturbed using spherical harmonics.

Due to the nature of the algorithm, either the latitudinal or longitudinal seams of the generated surface (or both) may not line up. Thus, by default, this method does not try to automatically join them together. In some shapes the seams do line up, in which case you can use the PD.Shape#weld method to join the matching seams so that you can use some of the modifiers that require a manifold shape.

Alternatively, as shown in the more detailed example below, you can use the PD.Shape#openEdgeLoops method to access the open seams and then manually join them up, in this case using a triangular fan.

Parameters:
Name Type Argument Description
config object <optional>

A optional configuration object.

Properties of config:
Name Type Argument Description
params Array.<Array.<number>> <optional>

An array of between 8 (shape) to 16 (shell) parameters.

core number <optional>

An inner core radius as a fraction (0 to 1), defaults to 0.

latRings number <optional>

The number of latitudinal divisions in 180deg (1 to 178), defaults to 36.

lngRings number <optional>

The number of longitudinal divisions in 360deg (3 to 360), defaults to 72.

normalise boolean <optional>

When true, ensures the maximum surface radius is 1, defaults to false.

random boolean <optional>

When true, generates random shape parameters, defaults to false.

innerRadius number <optional>

A fraction internal radius (-F to F), defaults to 'param[8]' (0).

helix number <optional>

A helical offset factor with longitude (-F to F), defaults to 'param[9]' (0).

spiralU number <optional>

A spiral inset factor with longitude (-F to F), defaults to 'param[10]' (0).

spiralV number <optional>

A spiral inset factor with latitude (-F to F), defaults to 'param[11]' (0).

rotationsU number <optional>

Number of longitudinal rotations (0 to R), defaults to 'param[12]' (1).

rotationsV number <optional>

Number of latitudinal rotations (0 to R), defaults to 'param[13]' (1).

scaleXY number <optional>

A horizontal scale factor (0 to S), defaults to 'param[14]' (1).

unfoldZ number <optional>

A vertical unfolding factor (0 to S), defaults to 'param[15]' (0).

usedParams Array.<number> <optional>

An optional array to receive shape parameters after range checks and validation.

Returns:

Returns a new shape with a spherical harmonics surface.

Type
PD.Shape
Examples
const usedParameters = []; // Get validated and range limited parameters.
const shape = PD.Shape.sphericalHarmonics({ random: true }, usedParameters).setRadius(2500);
console.log(usedParameters); // Show parameters actually used.
CAD.add(shape);
const params = [ 1, -3, 1, -4, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0 ];
const shape = PD.Shape.sphericalHarmonics({ params: params, innerRadius: 0.75 }).setRadius(2500);
CAD.add(shape);
const superShapeConfig = {
    params: [ 1, 4, 0, 0, 0, 0, 2, -3 ], // An array of 8 (shape) to 16 (shell) parameters.
    latRings: 18,       // The number of longitudinal divisions (1 to 178), defaults to 36.
    lngRings: 36,       // The number of latitudinal divisions (3 to 360), defaults to 72.
    normalise: false,   // When true, ensures the maximum surface radius is 1, defaults to false.
    random: false,      // When true, generates random shape parameters, defaults to false.
    innerRadius: 0.5,   // A fraction internal radius (-F to F), defaults to 'params[8]' (0).
    helix: 0.0,         // A helical offset factor with longitude (-F to F), defaults to 'params[9]' (0).
    spiralU: 0.0,       // A spiral inset factor with longitude (-F to F), defaults to 'param[10]' (0).
    spiralV: 0.0,       // A spiral inset factor with latitude (-F to F), defaults to 'param[11]' (0).
    rotationsU: 1.0,    // Number of longitudinal rotations (0 to R), defaults to 'param[12]' (1).
    rotationsV: 1.0,    // Number of latitudinal rotations (0 to R), defaults to 'param[13]' (1).
    scaleXY: 1.0,       // A horizontal scale factor (0 to S), defaults to 'param[14]' (1).
    unfoldZ: 0.75       // A vertical unfolding factor (0 to S), defaults to 'param[15]' (0).
};

const shape = PD.Shape.sphericalHarmonics(superShapeConfig).scale(2000);

/// Collect open edges and fill in top/bot holes.
const open_edges = shape.weld().openEdgeLoops();
for (const loop of open_edges) {
    const center = shape.faceCenter(loop);
    const center_index = shape.vertices.push(center) - 1;
    for (let ii = 0, ii_max = loop.length; ii < ii_max; ++ii) {
        shape.faces.push([ center_index, loop[ii], loop[(ii + 1) % ii_max] ]);
    }
}

CAD.add(shape.join());

superFormula( [config] [, usedParams]) <static>

Generates a cylindrical surface of unit radius perturbed using the super-formula.

Parameters:
Name Type Argument Description
config object <optional>

A optional configuration object.

Properties of config:
Name Type Argument Description
params Array.<Array.<number>> <optional>

An array of between 8 (shape) to 16 (shell) parameters.

latRings number <optional>

The number of latitudinal divisions in 180deg (1 to 178), defaults to 36.

lngRings number <optional>

The number of longitudinal divisions in 360deg (3 to 360), defaults to 72.

normalise boolean <optional>

When true, ensures the maximum surface radius is 1, defaults to false.

random boolean <optional>

When true, generates random shape parameters, defaults to false.

innerRadius number <optional>

A fraction internal radius (-F to F), defaults to 'param[8]' (0).

helix number <optional>

A helical offset factor with longitude (-F to F), defaults to 'param[9]' (0).

spiralU number <optional>

A spiral inset factor with longitude (-F to F), defaults to 'param[10]' (0).

spiralV number <optional>

A spiral inset factor with latitude (-F to F), defaults to 'param[11]' (0).

rotationsU number <optional>

Number of longitudinal rotations (0 to R), defaults to 'param[12]' (1).

rotationsV number <optional>

Number of latitudinal rotations (0 to R), defaults to 'param[13]' (1).

scaleXY number <optional>

A horizontal scale factor (0 to S), defaults to 'param[14]' (1).

unfoldZ number <optional>

A vertical unfolding factor (0 to S), defaults to 'param[15]' (0).

usedParams Array.<number> <optional>

An optional array to receive shape parameters after range checks and validation.

Returns:

Returns a new shape with a super-formula surface.

Type
PD.Shape
Examples
const usedParameters = []; // Get validated and range limited parameters.
const super_shape = PD.Shape.superFormula({ random: true }, usedParameters).setRadius(2500);
console.log(usedParameters); // Show parameters actually used.
CAD.add(super_shape);
const params = [ 5, 4, 12, 11, 2, 6, 4, 15, 0, 0, 0, 0, 1, 1, 1, 0 ];
const super_shape = PD.Shape.superFormula({ params }).setRadius(2500);
CAD.add(super_shape);
const shapeConfig = {
    params: [],         // An array of between 8 (shape) to 16 (shell) parameters.
    latRings: 36,       // The number of latitudinal divisions (1 to 178), defaults to 36.
    lngRings: 72,       // The number of longitudinal divisions (3 to 360), defaults to 72.
    normalise: false,   // When true, ensures the maximum surface radius is 1, defaults to false.
    random: false,      // When true, generates random shape parameters, defaults to false.
    innerRadius: 0.5,   // A fraction internal radius (-F to F), defaults to 'params[8]' (0).
    helix: 0.0,         // A helical offset factor with longitude (-F to F), defaults to 'params[9]' (0).
    spiralU: 0.0,       // A spiral inset factor with longitude (-F to F), defaults to 'param[10]' (0).
    spiralV: 0.0,       // A spiral inset factor with latitude (-F to F), defaults to 'param[11]' (0).
    rotationsU: 1.0,    // Number of longitudinal rotations (0 to R), defaults to 'param[12]' (1).
    rotationsV: 1.0,    // Number of latitudinal rotations (0 to R), defaults to 'param[13]' (1).
    scaleXY: 1.0,       // A horizontal scale factor (0 to S), defaults to 'param[14]' (1).
    unfoldZ: 0.75       // A vertical unfolding factor (0 to S), defaults to 'param[15]' (0).
};

const super_shape = PD.Shape.superFormula(shapeConfig).scale(1250);

/// Collect open edges and fill in top/bot holes.
const open_edges = super_shape.weld().openEdgeLoops();
for (const loop of open_edges) {
    super_shape.faces.push(loop);
}

/// Smooth edges, set size and add to CAD model.
super_shape.weld().join().setHeight(5000).setRadiusXY(2500);
CAD.add(super_shape);

tesselateSphericalArc(center, v1, v2, angularResolution [, stepsOverride]) <static>

Progressively tessellates a line between two points on the surface of a unit sphere until the given angular resolution is reached.

NOTE: This method requires that the points be normalised vectors, which basically means being coordinates of points on the surface of a unit sphere (having radius of 1) and centered at the origin ([0,0,0]).

Parameters:
Name Type Argument Description
center Array.<number>

The center of the sphere as an [x,y,z] coordinate array.

v1 Array.<number>

The first normalised surface point as an [x,y,z] coordinate array.

v2 Array.<number>

The second normalised surface point as an [x,y,z] coordinate array.

angularResolution number

The minimum angular resolution for subdivision.

stepsOverride number <optional>

An optional number of absolute subdivisions to use instead of the angular resolution.

Returns:

An array of segmented points as [x,y,z] coordinate arrays.

Type
Array.<Array.<number>>

tesselateSphericalQuad(v1, v2, v3, v4, angularResolution [, stepsOverride]) <static>

Progressively tessellates a quadrilateral of points on a unit sphere until the given angular resolution is reached.

NOTE: This method requires that the points be normalised vectors, which basically means being coordinates of points on the surface of a unit sphere (having radius of 1) and centered at the origin ([0,0,0]).

Parameters:
Name Type Argument Description
v1 Array.<number>

The first normalised surface point as an [x,y,z] coordinate array.

v2 Array.<number>

The second normalised surface point as an [x,y,z] coordinate array.

v3 Array.<number>

The third normalised surface point as an [x,y,z] coordinate array.

v4 Array.<number>

The fourth normalised surface point as an [x,y,z] coordinate array.

angularResolution number

The minimum angular resolution for subdivision.

stepsOverride number <optional>

An optional number of absolute subdivisions to use instead of the angular resolution.

Returns:

An array of quads, each with four [x,y,z] coordinate arrays.

Type
Array.<Array.<number>>

tesselateSphericalTriangle(v1, v2, v3, angularResolution [, stepsOverride]) <static>

Progressively tessellates a triangle of points on the surface of a unit sphere until the given angular resolution is reached.

NOTE: This method requires that the points be normalised vectors, which basically means being coordinates of points on the surface of a unit sphere (having radius of 1) and centered at the origin ([0,0,0]).

Parameters:
Name Type Argument Description
v1 Array.<number>

The first normalised surface point as an [x,y,z] vector array.

v2 Array.<number>

The second normalised surface point as an [x,y,z] coordinate array.

v3 Array.<number>

The third normalised surface point as an [x,y,z] coordinate array.

angularResolution number

The minimum angular resolution for subdivision.

stepsOverride number <optional>

An optional number of absolute subdivisions to use instead of the angular resolution.

Returns:

An array of normalised triangles, each with three [x,y,z] coordinate arrays.

Type
Array.<Array.<number>>

triakis(shape [, sides] [, offset]) <static>

The Conway triakis operation divides specified faces into triangles to form a pyramid with its apex at the center of the face.

If the sides argument is less than 3, all faces in the shape will be divided. If 3 or more, only those faces with a matching number of sides will be divided.

If an offset value is given, then the apex of the pyramid will be positioned that far away from the geometric centre of the face in the direction of its surface normal.

This method differs from the Conway Polyhedron Notation version in that the offset distance is given in model units rather than as a fraction of shape radius.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to base the operation on.

sides Array.<number> | number <optional>

An optional array of face indexes or the number of sides a face must have to be affected, defaults to 0 (all faces).

offset number <optional>

The distance of the pyramid apex away from the face center in model units, defaults to 0.

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape

truncate(shape [, sides] [, offset]) <static>

The Conway truncate operation is a triakis operation performed on the dual of the original shape, then converted back to a dual.

If the sides argument is less than 3, all faces in the shape will be bevelled. If 3 or more, only those faces with a matching number of sides will be bevelled.

Parameters:
Name Type Argument Description
shape PD.Shape

The shape to base the operation on.

sides Array.<number> | number <optional>

An optional array of face indexes or the number of sides a face must have to be affected, defaults to 0 (all faces).

offset number <optional>

The distance of the triakis apex away from the face center in model units, defaults to 0.

Returns:

Returns a new shape generated from the given shape.

Type
PD.Shape
Example
const poly = new PD.Polyhedron('D12:S4000');
CAD.add(PD.Shape.truncate(poly).setRadius(3765));
CAD.add(poly);

wedge(width [, depth] [, height] [, taperHeight] [, taperWidth]) <static>

Generates a wedge, which is similar to a cuboid but with an angled top and possibly also sides.

         Z
         |
         |                         Y
         4-------------------5__  /
         |'' 3---------------|---2
         |  /                |  /
         | /                 | /
         |/                  |/
         0-------------------1 -- -- X

A wedge shape tapers in the Y axis direction. It typically tapers in height, but may also taper in X axis width as it travels along the Y axis.

The taper height can be given as a single number or as an array containing the bottom and top heights at the taper end.

The taper width can also be given as a single number or as an array containing the left and right X-axis values at the taper end.

Parameters:
Name Type Argument Description
width number

The size of the wedge in the X-axis, defaults to 1.

depth number <optional>

The size of the wedge in the Y-axis, defaults to width.

height number <optional>

The size of the wedge in the Z-axis, defaults to width.

taperHeight number | Array.<number> <optional>

The height at the tapered end in the local Z-axis or a [min_z,max_z] array, defaults to [0,0].

taperWidth number | Array.<number> <optional>

The width at the tapered end in the local X-axis or a [min_x,max_x] array, defaults to [0,width].

Returns:

Returns a new wedge shape.

Type
PD.Shape
Examples
const wedge = PD.Shape.wedge(2000, 1500, 1000, 250);
CAD.add(wedge);
const wedge = PD.Shape.wedge(2000, 1500, 1000, 250, 500);
CAD.add(wedge);
const wedge = PD.Shape.wedge(2000, 1500, 1000, [ 250, 500 ], [ 1500, 2000 ]);
CAD.add(wedge);