Skip to content

6. Modify solids

raydeleu edited this page Nov 16, 2023 · 1 revision

6.1 What are modifications?

This section explains how to modify a 3D solid that was created using the functions and methods decribed in the previous chapter. Modifications as described in this section only relate to a single shape. Combining multiple shapes, through fusing, subtracting or intersecting, will be described in the next chapter.

The following table lists modifications that can be applied to a solid.

method description
.fillet(radiusConfig,filter?) round an edge of a shape with a fixed radius or a radius that is defined by a function. The filter refers to the selection mechanism defined in the next secion. It has the general shape of (e) => e.inDirection("X")
.chamfer(radiusConfig,filter?) take of a sharp edge by creating a transitional face, default at 45 degrees to a edge
.shell(thickness, (f) => f.inPlane("YZ",-20),{tolerance:number}) create a thin walled object from a shape, removing the indicated face from the shape to provide access to the hollow inside.
makeOffset(shape,thickness) create a shape that is offset from the original shape by the thickness. A positive number results in an increased size of the shape, a negative value will result in a smaller shape
.addHolesInFace(face,holeWires[]) create a hole in a shape using the wires that are indicated in the parameters to this function.

Most of the methods listed in the table require the selection of an edge or face of the shape. Therefore the next subsection will explain how edges and faces can be selected.

6.2 Selecting faces or edges for modification

Some of the methods listed in the previous subsection can be used without indicating a specific face or edge.For example, if a fillet is applied to a shape, the same radius of rounding is applied to all sharp edges in the shape. However, in most cases the fillet should be applied only to specific edges. In most visual CAD programs, the edges for the fillet operation are selected with the mouse cursor in the 3D view. In Replicad a filter mechanism has to be used to find the edges. The next paragraphs explain how faces or edges can be selected. Faces are relevant to create a thin walled object (shell) or to create holes in a face. Finding edges is relevant to create rounded edges (fillets) or chamfers.

6.2.1 Selecting faces

Faces can be selected using a FaceFinder object or using the so-called arrow notation of javascript. The arrow notation is a shorthand notation to define a function that changes the value of a given parameter. The following code explains this in more detail:

// create a variable as a new object to which a selection-method is applied
let foundFaces = new FaceFinder().inPlane("XZ",35)
// use this variable as an input to create a shell 
let hollowShape = solidShape.shell(thickness, (f)=>foundFaces,{tolerance:number})

// use the arrow notation to select a face directly as parameter to a method to change a shape 
let hollowShape = solidShape.shell(thickness, (f) => f.inPlane("YZ",-20),{tolerance:number})

The following methods to select faces are available:

method description
.inPlane("XZ",35) select all faces that are positioned in a given plane and offset
.parallelTo(plane/face/standardplane) select a face parallel to a given plane or face
.ofSurfaceType("CYLINDRE") select all faces of a certain type
"PLANE" / "CYLINDRE" / "CONE" /"SPHERE"/ "TORUS" / "BEZIER_SURFACE" /"BSPLINE_SURFACE"/"REVOLUTION_SURFACE"/"EXTRUSION_SURFACE"/ "OFFSET_SURFACE"/"OTHER_SURFACE" surface types to use with surfaceType selector
.containsPoint([0,-15,80]) select a face that contains a given point
.atAngleWith(direction,angle) select a face at a certain angle to an axis or plane atAngleWith("Z",20)
.atDistance(distance,point) select a face at a given distance to a point
.inBox(corner1,corner2) select a face that is partially located inside the given box
.inList(elementList[]) select a face that is in the elementList
find(shape,options), options {unique: true} returns all the elements that fit the filters

6.2.2 Selecting edges

Selecting edges works similar to selecting faces.

// create a variable as a new object to which a selection-method is applied
let foundEdges = new EdgeFinder().inPlane("XZ",35)
// use this variable as an input to create a shell 
let roundedShape = solidShape.fillet(radius, (e)=>foundEdges,{tolerance:number})

// use the arrow notation to select an edge directly as parameter to a method to change a shape 
let roundedShape = solidShape.fillet(thickness, (e) => e.inPlane("YZ",-20),{tolerance:number})

The following selection mechanisms can be used to find and select edges:

method description
.inDirection([x,y,z]/"X"/"Y"/"Z") find all edges that have the direction
.atAngleWith(direction,angle) atAngleWith("Z",20)
.ofLength(number) find all edges with a particular length
.containsPoint([0,-15,80]) find edges that go exactly through a point
.atDistance(distance,point) same as .containsPoint but allows some margin around the defined point
.inBox(corner1,corner2) finds all edges that are (partly) within a box
.inList(elementList[]) see issue https://github.com/sgenoud/replicad/issues/13, does not work yet
.inPlane(inputPlane,origin) inPlane("XY",30), find all edges that are exactly in the defined plane
.ofCurveType( ) find all edges of a certain curve type. "LINE", "BSPLINE_CURVE", "CIRCLE"
.parallelTo(plane / StandardPlane e.g. "XY") find all edges parallel to a stanadard plane
.shouldKeep todo? tbd

Note

When you reference faces or edges with their index, using the .inList method, you may experience the issue of the Topological Naming Problem. If the change to the design parameters results in a changing number of edges or faces, the fillet will no longer be applied to the correct edges. So use this method with care, if you only allow minor changes to the design such as using a different tolerance between two parts. Note that this selector currently does not work as expected, see issue https://github.com/sgenoud/replicad/issues/13.

6.2.3 Combine filters

method description
and both filters should be applied
either only one of the filters may be applied
not select all other edges than those selected by this filter
           const houseSides = new FaceFinder().either([
           (f) => f.inPlane("YZ", 50),
           (f) => f.inPlane("YZ", -50),]);
    
            const frontWindow = new EdgeFinder()
           .ofCurveType("CIRCLE")
           .not((f) => f.inPlane("XZ"));  

Below is an example how finders can be combined in the definition of a fillet.

let axleShape2 = axleHole2.fuse(keySlot2).sketchOnPlane("XZ",20)
let axle2 = axleShape2.extrude(25)
           .fillet(2,(e)=>e.either([
                         (e)=>e.inPlane("XZ",45),
                         (e)=>e.inPlane("XZ",20)]) )
return [axle2];

6.3 .fillet()

Note

Users of OpenCascade, the 3D kernel used by Replicad, have noticed that fillets may often cause the program to fail. This may result in a broken geometry (which will be reported as errors in other 3D applications such as slicers for 3D printers), or in the crash of the program. The best approach reported is:

  • if possible, try to add the fillets already in the sketching stage. There is no fillet command for sketches, but you can define arcs instead of sharp corners;
  • try to add the fillets to a completed shape as late as possible;
  • when a fillet fails, try to reduce the fillet size. OpenCascade cannot handle situations where a fillet completely removes an adjacent face. If you want to design such a geometry, try to find a different modelling approach to get the same result.
  • inspect the shape closely after filleting to determine if there are faces missing. This is a clear indicator for socalled non-manifold geometry, i.e. geometry that does not fully enclose a volume.

6.4 .chamfer()

6.5 .shell()

6.6 makeOffset()

6.7 addHolesInFace()