Skip to content

4. Create 3D wires and faces

raydeleu edited this page Nov 13, 2023 · 3 revisions

4.1 Create wires in 3D

In comparison to sketches which create wires or faces in 2D, the following functions create a wire in 3D. These wires can be used for example to create a 3-dimensional path for a sweep operation. This operation might be needed to create a tube that is bend in a 3-dimensional shape, such as the frame of a chair.

method description
makeLine([point],[point]) Create a straight 3D line
makeCircle(radius,[center],[normal]) Create a 3D circle wire
makeEllipse(major,minor,[center],[normal]) Create a 3D ellipse
makeHelix(pitch,height,radius,[center],[dir],lefthand?) Create a 3D helix, center and helix a [x,y,z]
makeThreePointArc([point1],[point2],[point3]) Create 3D arc through 3 points
makeEllipseArc(major,minor,anglestart,angleEnd,[center],[normal],[xDir?]) Create 3D ellipsoid arc
makeBSplineApproximation([points[],{bezierSplineApproximationConfig}) Create a 3D spline approximation through array of points
{tolerance:1e-3,smoothing:null/[x,y,z],degMax:6,degMin:1} bezierSplineApproximationConfig, configuration for spline
makeBezierCurve([points[]]) Create a 3D bezier curve through array of 3D points
makeTangentArc([startPoint],[tangentPoint],[endPoint]) Create a 3D tangent arc, tangentPoint is like vector
assembleWire([Edges]) ` Create a continuous edge from separate wires

4.2 Create faces in 3D

You can not only create wires in 3D but also complete faces. The difference between a wire and a face is that a face consists of a sketch or 3D wire that encloses a surface. This surface can be flat but also bend in space.

method description
makeFace(wire) Create a face from a wire consisting only of edges
makeNewFaceWithinFace(face,wire) Create a face on another face using a wire
makeNonPlanarFace(wire) Create a curved surface from a non-planar wire
makePolygon(points[]) Create a face from an array of points in a plane
makeOffset(face,offset,tolerance) Create an offset to a face
makePlaneFromFace() Extend a face out to an infinite plane parallel to this face
makeSolid(faces[]/shell) Create a solid from the volume that is defined by the array of faces or by a surface.

The following code example demonstrates how faces in 3 dimensions can be created using a quite complicated algorithm. In this example, the faces consisting of triangular surfaces are assembled in such a way that they completely enclose a volume, without leaving a gap. Using the method makeSolid the volume enclosed by these faces can then be converted to a solid. In the image below this is demonstrated by cutting a sphere out of the newly created shape. Note that without this final step, the faces represent infinitely thin surfaces floating in space. This might be sufficient to create a 3D shape for visualization, but does not allow 3D printing the object. The next section will explain the concept of shapes (solids) in more detail.

Icosahedron shape created from faces
function projectOnSphere(radius, vertex) {
  // function to project a vertex on to a sphere with radius "radius"
  let x = vertex[0];
  let y = vertex[1];
  let z = vertex[2];
  let currentRadius = Math.sqrt(
    Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)
  );
  let scale = radius / currentRadius;
  let scaledVertex = [scale * x, scale * y, scale * z];
  return scaledVertex;
}

const icosahedronFaces = (radius) => {
  let golden = (1 + Math.sqrt(5)) / 2;

  let v = [
    // vertices determined by 4 rectangles
    projectOnSphere(radius, [-1, golden, 0]),
    projectOnSphere(radius, [1, golden, 0]),
    projectOnSphere(radius, [-1, -golden, 0]),
    projectOnSphere(radius, [1, -golden, 0]),

    projectOnSphere(radius, [0, -1, golden]),
    projectOnSphere(radius, [0, 1, golden]),
    projectOnSphere(radius, [0, -1, -golden]),
    projectOnSphere(radius, [0, 1, -golden]),

    projectOnSphere(radius, [golden, 0, -1]),
    projectOnSphere(radius, [golden, 0, 1]),
    projectOnSphere(radius, [-golden, 0, -1]),
    projectOnSphere(radius, [-golden, 0, 1]),
  ];

  // faces added so that they always have an edge in common
  // with the previous ones
  return [
    [v[0], v[11], v[5]],
    [v[0], v[5], v[1]],
    [v[0], v[10], v[11]],
    [v[0], v[7], v[10]],
    [v[5], v[11], v[4]],
    [v[4], v[9], v[5]],
    [v[3], v[9], v[4]],
    [v[3], v[8], v[9]],
    [v[3], v[6], v[8]],
    [v[3], v[2], v[6]],
    [v[6], v[2], v[10]],
    [v[10], v[7], v[6]],
    [v[8], v[6], v[7]],
    [v[0], v[1], v[7]],
    [v[1], v[5], v[9]],
    [v[11], v[10], v[2]],
    [v[7], v[1], v[8]],
    [v[3], v[4], v[2]],
    [v[2], v[4], v[11]],
    [v[9], v[8], v[1]],
  ];
};

const main = (
  { makeSolid, sketchRoundedRectangle, makeSphere, makePolygon },
  {}
) => {
  function makeIcosahedron(radius) {
    const faces = icosahedronFaces(radius).map((f) => makePolygon(f));
    return makeSolid(faces);
  }

  // draw the isosphere
  let icosahedron = makeIcosahedron(2.0).scale(50);
  const sphere = makeSphere(100).translate([90, 30, 20]);
  
  // cut the icosahedron with a sphere to demonstrate that the first 
  // shape is indeed a solid, no longer collection of faces
  icosahedron = icosahedron.cut(sphere)

  let shapes = [
  {shape: icosahedron, name: "icosehadron", color: "steelblue"}
  ]
  return shapes;
};

The following code creates the shape of the OneWorld Trade Center in New York, which is a so-called anti-prism. The shape is created by defining the triangles that make up the shape and then stitching these together to create a solid.

image

const {draw, drawRectangle, makePolygon, makeSolid} = replicad;

function main()
{
let bL = 200/10;  // base length is 200 ft
let h = 1368/10;  // height 1368 ft
let m = (60/0.3048)/10; // first 60 meters are straight, converted to feet

    function antiPrism(bLength,prismHeight,endScale)
    {
        let bL = bLength/2;
        let tL = bL/Math.sin(Math.PI/4)
        let base=[]
        base[1] = [-bL,-bL,0];
        base[2] = [bL,-bL,0];
        base[3] = [bL,bL,0];
        base[4] = [-bL,bL,0];
        base[5] = base[1]   // trick to avoid need for modulus 4

        let top=[]
        top[1] = [0  ,-tL*endScale ,prismHeight]
        top[2] = [tL*endScale  , 0  ,prismHeight]
        top[3] = [0 ,tL*endScale  ,prismHeight]
        top[4] = [-tL*endScale ,0   ,prismHeight]
        top[5] = top[1]    // trick to avoid need for modulus 4

        let face=[]
        face[1] = makePolygon([base[1],base[4],base[3],base[2]]);        
        // not defined counterclockwise to have face facing in negative z-direction
        for (let i=2 ; i<=8; i+=2)
            {
            face[i]     = makePolygon([top[i/2],base[i/2],base[i/2+1]]);
            face[i+1]   = makePolygon([base[i/2+1],top[i/2+1],top[i/2]]);
            }
        face[10] = makePolygon([top[1],top[2],top[3],top[4]]);
        return face;
        }
let faces = antiPrism(bL,h,Math.sin(Math.PI/4));
let tower = makeSolid(faces).translate(0,0,m);
let towerbase = drawRectangle(bL,bL).sketchOnPlane("XY").extrude(m)
tower = tower.fuse(towerbase)
return tower}