Tuesday, April 8, 2014

Sectioning and Nesting in Grasshopper

I did some experimentation with the sectioning and nesting Grasshopper components available from RhinoNest. The idea was to see if I could interactively modify a 3D form, and have it quickly broken up into layered parts, then have these laid out on sheet stock.

Here's the test form I used - it's about 22" across and 2" thick.

Here's the Grasshopper definition.Inputs are the object(s), sheet thickness and size, and distance between parts. (The link to download is at the bottom of this post).  

The definition takes the 3D form, breaks it up into layers of the specified thickness, and then nests them on the sheet(s). In the image below a 48" x 48" sheet at 0.7" thick was specified.

This example was sectioned and nested in only 3 seconds. I consider that fast enough to be interactive!

You can download the RhinoNest demo and use it for 30 days. The download includes the Grasshopper components.

This link is to the zip file with the Grasshopper definition and a Rhino sample file: Download Here

Friday, March 21, 2014

Rotating Model Stand / Sculpture Pedestals

I just finished a couple of quick CNC projects. One was a rotating stand for a figure model to stand, sit, or lie on. The other was a few sculpture pedestals to donate to my son's school.

Rotating Model Stand

This stand was built for use in our sculpture studio (West Huron Sculptors) to let us rotate the model rather than have the sculptors move around the model. Here's the design which is meant to break down for easy storage when not in use:

The rectangular top is removable and is used for more stretched out poses. 

An exploded view: Eight milk crates, a single 17" lazy susan bearing, six 1" ball bearing rollers, two 4' diameter baltic birch plywood circles, three Poplar 2x4s, and a plywood top. 

This was very simple 3-axis CNC routing.

Installing the Lazy-Susan bearing and the six 1" ball bearing rollers. That'll support about 500 pounds - and so far all our models have weighed less than that...

These were purchased at Lee Valley and Woodcraft: Lazy-Susan Bearing, Ball-Bearing Rollers

Routing the notches for the rails to overlap the rotating base plate. The router was balanced between the rail and two pieces of MDF along side it.

The corners were sawn out and cleaned up with a chisel and chisel plane.

Here's the stand in our studio with a double stack of crates. The bottom circle has guides to prevent the crates from slipping. First without the top (good for a standing pose):

With the top on: 

Sculpture Pedestals

This project was a few simple 10" x 10" x 5" and 10" x 10" x 45" sculpture display pedestals. These were made to be donated to my son's school for use in the art department. These were CNC cut with a 3/8" down-shear and a 3/8" compression bit.

The taller stands had a few small joints at the top and bottom then a long one in between:

The interesting thing about them is the joint design and the resulting corner condition which gives them a bit of detail rather than being completely straight-forward boxes. You can see how the joints go together here and the corner detail at the top left:

These were painted satin black by my son and his friends and donated to Washtenaw International High School.

Monday, February 24, 2014

Surface Rough and Surface Finish Toolpath Setup

This post documents the process of setting up a 3-axis surface roughing and surface finishing of sheet material using Mastercam.

Setting up the machine and stock, as well as backplotting and simulation, is exactly the same as is shown in the Mastercam Toolpath Setup post. This post will cover adding a surface roughing and surface finish toolpoaths.

Surface Roughing Toolpath

Surface roughing toolpaths typically use larger tools, multiple stepovers, and multiple step downs to quickly remove larger volumes of stock and leave an even amount of stock for finishing. The roughing toolpaths you choose for your part depend on the shape of the part, shape of the stock, and machining situation.
Check out the Mastercam help file for details on the various roughing strategies shown below. This post will use the Parallel toolpath.

You'll be asked to select the surfaces to cut to via the selection dialog:

  • Drive: The surfaces, solid faces, solid bodies, or CAD files that will be cut.
  • Check: The surfaces, solid faces, or solid bodies that you want the tool to avoid. 
  • Containment: A closed chain of curves that limit tool motion. 

 Click the arrow under Drive and choose the surfaces to cut. Once selected exit the dialog.

As with other toolpaths you need to choose a tool. For small MDF panel surfacing projects a good choice is a 1/2" downshear rougher.

Once selected change the tab over to the Surface parameters options.

Here you set the Retract and Feed Plane settings. Retract sets the height that the tool moves up to before the next tool pass. Select the check box to activate the retract plane, then click the button and select a point on the geometry or enter a value. This option is off by default. The retract height should be set above the feed plane. If you do not enter a Clearance height (clearance sets the height at which the tool moves to and from the part), the tool will move to the retract height between operations.

Next set the Stock to leave on drive surfaces. This will leave the extra amount that the finishing pass removes. Leaving 1/8" or 1/4" is fine for MDF. This lets the smoother finishing pass clean down to the actual drive surface height.

Next change the tab to set the Rough parallel parameters.

The Maximum stepover controls how far the tool moves over for each cut in XY, and the Maximum stepdown controls how much material is removed in Z for each cut. You can safely use 80% of your too width for the step over provided you are not stepping down to much in each pass. When surfacing MDF I like to step down no more than twice the tool width, and step over about 50% of the tool width on each pass.

Use the Plunge control parameters to control where the tool is allowed to make plunges. Use the buttons to set cut depths, control motion between adjacent surfaces, and motion on surface edges.

Change the Cutting method to Zigzag. Under Plunge control select the Allow multiple plunges along cut. This makes multiple entry moves along the part. This will significantly speed up the cutting time.

Check both the Allow negative Z motion along the surface and Allow positive Z motion along the surface. This will maximize the speed of the roughing as the tools we are using can cut while plunging and while retracting.

Surface Finishing Toolpath

Surface finishing toolpaths typically finish a part down to the drive geometry (or to the stock to leave amount if one is specified). These are usually using a small stepover and don't cut very deep. To surface a 3D form a typical stepover is 0.05". The typical amount of material being removed might be 0.25" or 0.125".

To add this toolpath right-click in the Toolpath group and choose a Surface Finish toolpath. In this example I'm using Parallel.

You'll be asked to select the Drive surfaces as in roughing.

Next you'll be asked to select a tool. For surfacing choose a ball end mill. Choose the largest tool that can still get everywhere into your parts form. Using a larger tool gives a shallower scallop making for a cleaner surface. In this example I'm using a 1/2" ball end mill.

Next move to the Surface parameters tab.

Here you set the Retract and Feed plane values as above. Make sure the Stock to leave on drive is set to 0.0 so it mills all the way to your surface.

Next move to the Finish parameters tab.

Finish parallel toolpaths cut the drive geometry using linear zigzag or one-way motion. In this example we'll set the Cutting method to Zigzag. 

The Maximum stepover controls how far the tool moves over for each cut in XY. Using a smaller value will result in a smoother surface but take more time. For a 1/2" ball bit I like a value of around 0.05" as the stepover. 


Make sure to carefully simulate your roughing and finishing cuts. 
Control of Simulation is the same as was shown in the Mastercam Toolpath Setup post. 

3D Contour Toolpath (Waste Trim)

If you want the router to trim the waste from your panels you can use a 3D Contour toolpath to do so.
Note: Since the toolpath will need to cut entirely through the material, doing this will compromise your form for future vacuum forming of panels. Therefore, make sure you have an extra form for trimming, or have enough panels already cut!

Right-click in the toolpath list and choose Router toolpath > Contour from the menu.

The Chaining dialog will appear and you select the chain to cut. Careful setup in Rhino to create a single closed curve will make this setup process easier in Mastercam.

After you select the Chain the Contour toolpath dialog will appear. First select the tool. I'm using a 1/4" straight downshear.

Next go to the Linking Parameters branch. Set your Retract, Feed plane, and Top of stock values.

Next go to the Cut Parameters branch. Make sure the Contour type is set to 3D. You'll also need to set the Compensation direction to right or left. After you simulate you can easily tell if you need to switch the setting if it is cutting on the wrong side of the line.

You may also want to set a small Break Through amount using that branch. Here you can set a low value to cut through the material to make sure it is fully free from the waste.

You can then backplot or simulate to make sure the Contour is cutting as expected.

Sunday, February 16, 2014

Rhino 3dm File Load / Draw / Bake

As part of getting an interactive preview into the Super Matter Tools UI I've been developing some proof-of-concept code to read Rhino 3dm files, load the objects into memory (without creating Rhino geometry), and draw them using a fast "display conduit". Further, I've worked on posing those objects (transforming them), and then "baking" them into actual Rhino geometry so they can be used to render animations.

This is similar to how Grasshopper lets users preview geometry and manipulate it without creating Rhino objects. Then, when things are set, baking them.

Here are a few screen captures of the code running (the full source code is listed at the end of this post):

A Kuka KR100HAL90 robot mesh, drawn shaded using the display conduit. The bounding box for the objects is expanded by 5% and drawn as well. For an overview of the Display Conduit in Rhino see this post: Display Conduit Introduction for RhinoCommon.

 The material diffuse color is changed to green and drawn again:

 The robot is rotated 90 degrees in Z, material is changed, and drawn:

The mesh is "baked", converting them to Rhino objects: 

This allows for drawing using the nicer rendering modes available - in this case Artistic:

The full python test code:

import rhinoscriptsyntax as rs
import scriptcontext
import Rhino
import System
import System.Drawing

def Main():
    # The 3dm file to open and read
    pathname = "C:\\KR100HAL90.3dm"
    # Open it and get the objects
    drawObjs = Load3DMFile(pathname)
    # Make the display conduit object for drawing
    dc = DisplayConduit(drawObjs)
    # Draw
    dc.xform = rs.XformIdentity()
    dc.Enabled = True
    rs.GetPoint("Click to continue...") # Wait...
    # Change the material color and draw again
    dc.material.Diffuse = System.Drawing.Color.Green
    rs.GetPoint("Click to rotate...") # Wait...
    # Rotate (and change color again)
    cplane = rs.ViewCPlane()
    dc.xform = rs.XformRotation2(90.0, cplane[3], cplane[0])
    dc.drawObjsBBox.Transform(dc.xform) # Update the bounding box to the rotated state
    dc.material.Diffuse = System.Drawing.Color.Yellow
    rs.GetPoint("Click to Bake Meshes...") # Wait
    # Convert the mesh to Rhino objects
    meshList = BakeMeshes(dc.drawObjs, dc.xform)
    if meshList:
        print "Meshes created: %d" % len(meshList)
    # Stop drawing
    dc.Enabled = False

# Read the 3dm file and return a list of the objects within it
def Load3DMFile(pathname):
    f3dm = Rhino.FileIO.File3dm.Read(pathname)
    if (f3dm):
        objs = f3dm.Objects
        return objs

# Convert the list of objects passed to Rhino geometry. Then transform
# them with the transformation matrix passed
def BakeMeshes(drawObjs, xform):
    meshList = []
    for item in drawObjs:
        if item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Mesh:
            mesh = item.Geometry
            verts = mesh.Vertices
            faces = mesh.Faces
            rhinoMesh = scriptcontext.doc.Objects.AddMesh(mesh)
    if (meshList):
        rs.TransformObjects(meshList, xform)
    return meshList

# Display Conduit class to draw in the viewports
class DisplayConduit(Rhino.Display.DisplayConduit):
    def __init__(self, objs):
        # Store the objects we are to draw
        self.drawObjs = objs
        # Store the transformation to apply - initially none
        self.xform = Rhino.Geometry.Transform.Identity
        # Get the bounding box for all the objects passed
        self.drawObjsBBox = Rhino.Geometry.BoundingBox(Rhino.Geometry.Point3d(-1,-1,-1), Rhino.Geometry.Point3d(1,1,1))
        for item in self.drawObjs:
            bbox = item.Geometry.GetBoundingBox(False)
            if (bbox):
        # Expand the bbox by 5% of the diagonal length for use in zoom extents
        amount = self.drawObjsBBox.Diagonal.Length*0.05
        # Init the material to draw with
        self.material = Rhino.Display.DisplayMaterial()
        self.material.Diffuse = System.Drawing.Color.OrangeRed # Kuka robot color!
        self.material.Shine = 0.8
    # Called to quickly return the bounding box for the scene including our objects
    def CalculateBoundingBox(self, calculateBoundingBoxEventArgs):
    # Called to quickly return the zoom extents bounding box including our objects
    def CalculateBoundingBoxZoomExtents(self, calculateBoundingBoxEventArgs):
    # Called to draw the objects to the viewport. This is done before any Rhino
    # objects which will be drawn over ours.
    def PreDrawObjects(self, drawEventArgs):
        drawEventArgs.Display.DrawBox(self.drawObjsBBox, System.Drawing.Color.White)
        drawEventArgs.Display.PushModelTransform(self.xform) # Apply the transform
        for item in self.drawObjs:
            if item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Curve:
                drawEventArgs.Display.DrawCurve(item.Geometry, System.Drawing.Color.Green)
            elif item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Brep:
                drawEventArgs.Display.DrawBrepWires(item.Geometry, System.Drawing.Color.Red)
            elif item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Mesh:
                #drawEventArgs.Display.DrawMeshWires(item.Geometry, System.Drawing.Color.Blue)
                drawEventArgs.Display.DrawMeshShaded(item.Geometry, self.material)
            elif item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Point:
                drawEventArgs.Display.DrawPoint(item.Geometry.Location, System.Drawing.Color.White)
        drawEventArgs.Display.PopModelTransform() # Remove the transformation

# Run it...
if (__name__ == "__main__"):

Sunday, February 2, 2014

CNC Corner Fix Utility

I created a Rhino Python script to quickly draw the geometry to allow the CNC router to clear out material in corners.

Download Here
(Note: This a Windows only plug-in. It will not work with Rhino for the Mac.)

To run the script load it into the Rhino Python editor. From Rhino type EditPythonScript. This launches the Python editor.

Choose the Open icon and load the CornerFix12.py script. Select Run Script from the fly-out menu shown.

The user interface is shown below.

Choose if you want to clean the corner material with a Router bit or a Drill bit. You can use a drill bit with a small diameter to make the least visible mark. Choose Router if you don't want to change tools and just cut the contour into the corner.

Choose the diameter of the bit you wish to use. Then set the Shift Cut %. For the least visible cut use the default of 99%. This will just barely cover the corner. If you change it to 0% the arc will be centered over the previous intersection point. Here are a few example of a router path to visualize the difference (the polylines intersect on the grid intersection points):

Click the Select Lines button. Select the two line segments leading into an inside corner. The arc will be drawn. Note: The program always draws to the inside corner - there is no reason to add arcs to outside corners because they can be cut without them. If you are using a drill bit a center point is drawn as well as the circle. Not trimming of the corner is done.

There is an extra 0.001" added to the width of the arc and lines drawn when routing. This allows CAM software toolpaths to enter the arc. Without this, particularly in Mastercam, the corner arc will be skipped.

Note you can fully operate Rhino as the script runs. This lets you explode, undo, join, whatever... as you fix up the corners. To quit the program just close the interface.

Important Safety Note

If you make the corner curve very small (as is shown above) you run the risk of burning the material. That's because the router bit is not moving much as it clears the corner material. This leaves the bit spinning in place (or almost so) and heats it way up. Therefore be careful when using the circle setting. It's better to drill the holes (for the smallest amount of material removed from the corner) or use a larger circle so the bit will continue to move as it clears out the corner. That is, use a diameter larger than the bit.

Here's an example of the burn that can occur - this is doing some pocketing (before the finish pass was cut):

In this case, there were so many corners cut this way, the bit go so hot that the spoil board beneath the material caught fire. That's never good!

Current Limitations:
  • The program works on degree 1 curves only (polylines). 
  • The polylines need to be open. So if you have a closed polyline explode it first, then use the tool. 
  • The polylines need to intersect at a point or cross over one anther. If they don't fillet them with a radius of 0 first. Then select the lines. 

Sunday, January 26, 2014

Traditional Wood Joinery / CNC Wood Joinery

In learning about CNC cut joinery it is well worth looking at traditional wood joints as they have been cut for many years. This will help develop an understanding of the conditions affecting wood joints, and some of the solutions that have been created to deal with them.

The constraints of using the CNC router, even a 5-axis machine, makes clear that joints which are specifically designed for the process are the most suitable.

Traditional Wood Joints

Wood joints can be categorized in many ways. One method is to break them into the four groups as shown below:

To understand the application of each of these joints let's look at a simple bookcase and see how each joint type is used in its construction. 
This case has two long sides. A fixed top and bottom. A face frame to give the side edges some extra width. And three movable shelves. The shelves have a wider board along the front edge to give them some extra width. The bookcase also has trim boards around the top and bottom. 

Edge-to-Edge Joints

Edge joints are used in attaching boards, well, on edge. Here's an example from the bookcase - the trim board on the edge of the shelf is joined along its length to the shelf:

Edge joints are also used to attach boards together to make up wider panels. Gluing wide panels from narrower boards helps with the stability of the panel in resisting cupping and warping.  

Here are typical edge joints: 

Housing Joints 

Housing joints are often used in case construction. Here's an example from the bookcase - the lowest shelf is dado-ed into the side panel providing a strong bottom and racking resistance to the case. 

Here are typical housing joints: 

Corner Joints

Corner joints, as the name implies, are used in joining pieces at a corner. Here's the example from the bookcase - the trim board on the base has mitered corners. So does the molding at the top.

Here are some typical corner joints:

Frame Joints

Frame joints are used in creating face frames in cabinetry. Here's an example from the bookcase - the frame which hides the edge uses frame joints. In this case a long half lap:

Here are some typical frame joints:

Difficulties of CNC Cut Joinery

There are some difficulties associated with CNC cut joinery which need to be worked around. 
  • Square corners can’t be cut with round router bits. For many cases this means custom joints need to be designed with rounded corners.
  • Rather than moving the work piece over the tool, usually the work must be held securely while the tool moves. This added fixturing adds complexity, greater time, and extra material costs to a project. 
  • Router bits as compared to saw blade cutting – tear out on the edge of pieces is more problematic with router bits. This needs to be carefully setup so the tool approaches the work properly. Router bits also exert more force on the workpiece while cutting necessitating stronger fixturing. 

CNC Cut Joints

Using a CNC router makes certain joint conditions doable whereas with traditional tools they would be impractical. For instance a curved tongue and groove joint, box joints cut into curved pieces, curved miter joints, and half lap joints which occur at angles and along curved edges.

There are many interesting joints which can be easily cut on the CNC router which would be very time consuming if done with traditional shop tools. Some examples are shown below. Note that these examples are all from the research done by Jochen Gros and Friedrich Sulzer: Digital Wood Joints. Many of those joints are CNC-modified variations on the joints above. Some of the more complex example have precedents in Japanese joinery.