Workflow: Building the Workpiece from a Reference Mesh
A customer often sends the part as one mesh exported from a CAM verification tool rather than as a labelled stock model and a labelled design model. Such a mesh is in the CAM tool's frame, not the program's, and it may be the stock before an operation, the stock after it, or the design surface — its file name rarely says which. This page turns it into a workpiece: decide what the mesh is, find program zero in it, then build the target and the stock from it, by hand or over the HTTP API.
It is step 3 of the build order in Project Construction.
flowchart LR
What["1 · What is the mesh?<br>distance test"]
Zero["2 · Program zero<br>in the mesh frame"]
Build["3 · Target + stock<br>one frame"]
Parts["4 · Several parts?"]
Api["5 · API calls"]
What --> Zero --> Build --> Parts --> Api
Zero -->|refine| What
1. Decide what the mesh is
Using the wrong reading produces a run that finishes without an error. A finishing program played on the surface it is meant to leave only grazes it: steps report contact, the forces come out near zero, and no message is raised, because the no-contact warning fires only when not a single step of the whole play touched the workpiece.
Test the mesh against the program before building anything. For a ball-nose cutter of radius R, move every tool-tip point of the program up by R along the tool axis to get the ball centre, and measure each centre's distance to the mesh:
| Distances cluster at | The mesh is |
|---|---|
| R, across the whole part | the surface this program leaves — use it as the target, not as the stock |
| R − a, with a roughly constant | stock carrying an allowance a for this program — the ball sinks a into it; once a exceeds R the centres fall inside the mesh, at a − R |
| scattered, many centres inside the mesh | a surface from another operation, or program zero is in the wrong place |
A flat-bottomed cutter gives the same test more simply on floors: the tip Z of each floor pass equals the height of the floor it leaves.
2. Find program zero in the mesh's frame
CAM tools export in their own frame, often machine coordinates, so the mesh's origin is rarely the program's. Find the translation that carries the program onto the mesh:
- X and Y — register the program's footprint (the X–Y extent of its cutting moves, or a distinctive outline such as a pocket) onto a top-view height map of the mesh.
- Z — match the program's distinct floor depths to the flats of the mesh. A program with floors at Z −0.5, −2.5 and −4.5 must land on three flats exactly 2 mm apart; the offset between the two sets of numbers is program zero's height.
Refine all three with the distance test of §1: the right translation is the one that makes the distances most uniform, and a few tens of thousands of sampled tool points are plenty. Do not assume the usual convention — program zero on the top face of the stock — holds for the mesh: the fit decides. Write the translation, the spread of distances it leaves, and how it was found into the project's README.
The same fit is the Z-datum check for a finishing program, which has no layer depth to compare a peak cutting depth against.
3. Build target and stock from one mesh
Raw Geometry and Target Geometry hang from the same workpiece geometry frame, so put the same transform on the mesh in both and let it move program zero onto the geometry origin:
- Target Geometry — the mesh as a
StlFilewith a Static Translation on it, of minus program zero's mesh coordinates: the Transform picker on the StlFile item, or over HTTP aTransformationGeomholding theStlFile(§5). - Raw Geometry — the same transform, with the allowance added to the translation's Z when the mesh is the finished surface. When §1 showed the mesh to be the stock, it goes here with no allowance added, and the target comes from the design model.
- The branch to the Program-Zero Anchor — the workpiece branch from its Geometry Anchor to its Program-Zero Anchor: the identity, because the transform already put program zero at the geometry origin.
- The branch to the Fixture Mount — from the Geometry Anchor to the Fixture Mount: the bottom centre of the stock, as usual; the mesh's bounding box plus the transform's translation gives it.
A vertical lift is not a normal offset. It leaves the full allowance a on floors, a · cos θ on a face inclined at θ from the horizontal (about 0.7 a at 45°), and nothing on vertical walls. That is a fair stand-in for a finishing pass over mostly flat or gently sloped surfaces; for wall finishing, obtain the real pre-operation stock. When the allowance is unknown, pick a value typical for the finishing strategy — a tenth or two of a millimetre for a ball-nose finishing pass — record it as an assumption, and keep it a single parameter of the build so it can be changed and rebuilt. After changing it — or the Initial Resolution the stock is meshed at — delete the stage-0 record of the stock before the next run, or the run starts from the old one: see The stage-0 cache goes stale, silently.
4. Several parts, one program zero
A mesh often carries several identical parts machined side by side by one program — the same
subprogram called once under G54, once under G55, and so on. Model them as one workpiece
geometry and put program zero, as above, on the part the first offset serves: the workpiece has one
program-zero anchor, P0 writes that anchor's position whichever row it is pressed on, and every
further row is the first row plus the spacing between the parts' program zeros. Two parts 120 mm
apart along X on a three-axis machine give G55 = G54 + (120, 0, 0).
Run the distance test of §1 per part as well. When the mesh shows the parts at slightly different
heights while the recorded offsets say they are level, decide which to trust and write the choice
down; Several parts, several offsets
sets out both options. Keeping the recorded level offsets is the costly choice when a part sits lower
than the first by more than the allowance: its whole pass then plays above its stock and cuts nothing. A part played in the wrong
place raises no message of its own while another part is still cut, so check every part after the
run — IsTouched over each call's step range, as in
Replay Acceptance §6.
5. Over the HTTP API
Each slot takes the same sequence of calls. The keys are chosen by the caller — raw below; in
practice with a prefix no other caller of the service uses — and the service derives the inner ones
from them:
POST /api/Workpiece/CreateRawGeometry?geometryKey=raw&geometryType=TransformationGeom(the target slot:CreateIdealGeometry) — installs an empty transformation geometry in the slot.POST /api/TransformationGeom/CreateGeom?transformationGeomKey=raw&geometryType=StlFile— answers the inner key,raw-Geom.POST /api/StlFile/UpdateSourcewith{"StlFileKey": "raw-Geom", "RootName": "ProjectDirectory", "RelFile": "Geom/part.stl"}— stores the path project-relative and loads the mesh.POST /api/TransformationGeom/CreateTransformer?transformationGeomKey=raw&transformerType=StaticTranslationanswersraw-Transformer;POST /api/StaticTranslation/UpdateTrans?staticTranslationKey=raw-Transformer&x=…&y=…&z=…sets the translation.GET /api/StlFile/GetInfo?stlFileKey=raw-Geom— must answerloaded: trueand the triangle count the file really holds.- Re-install the slot so the run sees the edits made inside it:
POST /api/Workpiece/UpdateRawGeometry?geometryKey=raw, thenPOST /api/Workpiece/ClearRawGeomCache(for the target slot,UpdateIdealGeometryandClearIdealGeomCache).
Step 5 is not optional. A mesh that fails to load still answers step 3 with HTTP 200 and
success: true; the only sign is a warning field in the body, and the reference is stored anyway,
so the failure surfaces later and far from its cause. The same GetInfo answer carries the mesh's
bounding box in the mesh's own frame, which with the step-4 translation added gives the translation
of the branch to the Fixture Mount.
Step 6 is not optional either. Steps 2 to 4 edit objects inside the slot through their keys, and such an edit marks nothing: it reaches the copy of the setup the run is built from only at a fresh session — the first play after a load or a Reset — or when the slot is installed again. A play in a session still open from an earlier run plays the old stock, silently. Re-installing costs nothing, so do it after every nested edit. Why, and the same rule for the branch transformers, is Driving the Web Service over HTTP.
The two workpiece branches are not slots: each is a branch of the workpiece's topology, found through its graph and addressed by guid. For the branch to the Fixture Mount:
- Build the transformer under a key:
POST /api/StaticTranslation/NewWithValue?key=fm-xf&x=…&y=…&z=…. GET /api/mech/equipment-topology/graph. Inanchors, take the one withowner: "workpiece"whoserolesincludeFixtureMount; inbranches, take the one withowner: "workpiece",isAttachment: falseandarrowAnchorGuidequal to that anchor'sguid. When there is none, the role is unbound or the branch is missing — bind it in the workpiece's Roles panel, or add the branch, before going on.POST /api/mech/equipment-topology/workpiece/branch/{guid}/update-transformer?transformerKey=fm-xfinstalls it; the answer is the key it is re-indexed under, and posting that key to the same route is the re-install after any later nested edit.
The branch to the Program-Zero Anchor is the same three calls with the anchor whose roles include
ProgramZeroAnchor. PUT /api/Workpiece/init-resolution takes the Initial Resolution as a bare
number.
See Also
- Project Construction — the build order this page is one step of
- Program Zero Alignment — the two alignment directions, and several parts on several offsets
- Workpiece — the Raw and Target slots and the Initial Resolution in the app
- Geometry Validation — comparing the cut against the target built here
- Driving the Web Service over HTTP — keys, derived keys, re-installing a slot, and addressing a branch of the equipment topology