Skip to content

MCP command reference

CoCAD serves six generic MCP tools — list_commands, execute, query, undo, redo and get_screenshot — and everything else is a command those tools reach. That is the design, not a limitation: the command registry is the product, so an AI has full parity with the UI by construction, and a new feature is a new command, never a new tool an agent has to wait for.

The one list that is always right is the running program’s own: call list_commands (which walks query.commands) and you get every command the connected build registers, each with its JSON Schema. Read that at runtime rather than trusting any written list — this page included, because gated commands exist only where their library is linked. What this page adds is a readable, linkable copy of that registry for the shipping configuration, regenerated from the repository on every build.

360 commands, read verbatim from the registry's own query.commands on windows-kernel-solver (the configuration CoCAD ships), as of . This page is generated from that table on every build — it is never written by hand, and the build fails rather than publish a row it cannot parse.

Gates

Some commands exist only where their library is linked. The gate column below means:

  • desktop — needs the CoCAD desktop app. The installed app has it.
  • dxf — needs the DXF library. The shipping build has it.
  • pixels — needs image support. The shipping build has it.
  • not the fixture — present in the real app, and left out of the test build.
  • every build — registered in every configuration of the core.
  • kernel — needs the geometry kernel (OCCT). The shipping build has it.
  • solver — needs the sketch constraint solver (PlaneGCS). The shipping build has it.
  • fonts — needs font support (stb_truetype). The shipping build has it.
  • --allow-remote-shutdown — available only when the core was launched with this flag.

Documents & timeline

Creating, saving and opening documents, and walking the shared undo timeline — yours and any connected AI’s steps sit in one history.

doc.branch

Make a named branch of this document's timeline: a complete copy of the recipe as it stands, kept inside the document and saved in the .cocad beside it, so two ideas for one part can live in one file.

Detail

Make a named branch of this document's timeline: a complete copy of the recipe as it stands, kept inside the document and saved in the .cocad beside it, so two ideas for one part can live in one file. Does not switch to it - you stay on the branch you are on; doc.switch_branch opens it. The copy remembers which branch it was taken from and what that branch's recipe was at the time, which is what a later merge compares against. Names are unique within a document; a document that has never branched is on a branch called main. Not a step in the timeline and not undoable: it changes which recipes the document holds, not the part.

doc.close

Close one open document.

Detail

Close one open document. Unsaved work is discarded without asking, exactly as doc.new discards it: prompting belongs in the window, above the bus, because an AI calling this has no dialog to answer. Closing the last one leaves this core with nothing open, which is the state it starts in. A connection looking at the closed document lands on the one beside it.

doc.create_folder

Make a folder in the browser to organise this document - Fasteners, Frame, Old versions.

Detail

Make a folder in the browser to organise this document - Fasteners, Frame, Old versions. A folder is a way of arranging rows and nothing else: it changes no geometry, no position, no joint, no parts list, no export and no timeline order, so moving a body into one does not move the body. Bodies, sketches, component placements and other folders can be filed into it with doc.move_to_folder, and a filed thing is drawn inside the folder rather than in the Bodies or Sketches folder it would otherwise sit in - which is why the Bodies folder's count goes down when you file something. Name it now or let it be called Folder<n> and rename it later with doc.rename. Give a parent folder to nest it; leave parent out and it sits at the top of the document beside Bodies and Sketches. Saved with the file, and undoable - filing thirty rows in one drag is exactly the thing Ctrl+Z has to reach. Not a timeline feature: organising is not modelling.

doc.create_timeline_group

Group a run of ADJACENT timeline features under one name - base, mounting holes, cosmetics - so a long timeline reads as a handful of named stages.

Detail

Group a run of ADJACENT timeline features under one name - base, mounting holes, cosmetics - so a long timeline reads as a handful of named stages. A group is a way of reading the strip and nothing else: it changes no geometry, no rebuild order and no suppression, and grouping a feature does not move it. The features must sit next to each other in the timeline (query.features order) and not already be in a group - a feature is in one group at a time. Name it now or let it be called Group<n> and rename it later with doc.rename. Saved with the file, and undoable in one step. Not a timeline feature itself: organising is not modelling.

doc.delete

Delete bodies, sketches, construction planes, axes, points and coordinate systems - the modelling entities a person selects and presses Del on.

Detail

Delete bodies, sketches, construction planes, axes, points and coordinate systems - the modelling entities a person selects and presses Del on. One call is one undo, whatever the mix. What was built FROM the thing you delete stays: a rebuild replays the deletion after everything that used it, so deleting the sketch an extrude was made from keeps the extruded body and removes the sketch. The timeline keeps the feature that made a deleted body, having made something that later left; rolling the timeline back past the deletion brings the entity back. Deleting is refused where a saved picture would silently change what it shows - an explode state that offsets the body, a drawing view that draws it - and the refusal names it. Journaled, saved with the file, undoable, and it adds no timeline feature.

doc.delete_branch

Forget one of this document's branches that is not the open one, recipe and all.

Detail

Forget one of this document's branches that is not the open one, recipe and all. The open branch cannot be deleted - switch to another first. Not a step and not undoable; the branch is gone from the document and from its next save.

doc.delete_folder

Remove a browser folder.

Detail

Remove a browser folder. What was in it is NOT deleted: bodies, sketches and placements go back to the Bodies, Sketches and Placements folders they came from, and folders inside it move up to where it was. A folder is organisation, so deleting one must never delete a part - the reply says how many things were released so you can tell somebody where their parts went. Saved with the file, and undoable, which puts the folder and every filing back exactly as they were.

doc.delete_timeline_group

Remove a timeline group.

Detail

Remove a timeline group. The features that were in it are NOT deleted or moved: they stand exactly where they are in the timeline, ungrouped. A group is a way of reading the strip, so deleting one must never change the model - the reply says how many features were released. This is also the way out of a group that a move cannot empty. Saved with the file, and undoable, which puts the group and every membership back exactly as they were.

doc.move_to_folder

File things into a browser folder, or take them out of one.

Detail

File things into a browser folder, or take them out of one. Name what to move - bodies, sketches, component placements, other folders, in any mixture - and the folder they go into, or null to put them back where they would otherwise sit. This says where they now are, not how far to move them, so sending the same call twice files them once and a retry is safe. Nothing about the model changes: a folder is a way of arranging rows, so query.measure, query.tessellate, query.bom and every export answer exactly as before, and a part in a folder is manufactured the same way as a part not in one. A thing is in one folder at a time, so filing it somewhere takes it out of wherever it was, and a thing already there is a success that moves nothing. A folder cannot be filed into itself or into anything already inside it. Saved with the file, and undoable in one step, so a drag that files the wrong thirty rows is one Ctrl+Z.

doc.move_to_timeline_group

File timeline features into a group, or take them out of one.

Detail

File timeline features into a group, or take them out of one. Name the features and the group they go into, or null to take them out of whatever group they are in. This says where they now are, not how far to move them, so sending the same call twice files them once and a retry is safe. Every group must stay one unbroken run of adjacent features - filing something into the middle of another group, or pulling a feature out of the middle of its own, is refused with the group named. A feature already there is a success that moves nothing, and a move that would leave a group empty is refused - delete the group instead, which releases its features. Saved with the file, and undoable in one step.

doc.new

Create a new empty document and make it current.

Detail

Create a new empty document and make it current. Without keepCurrent it REPLACES the document this connection is on, and that document's unsaved work is discarded - the reply's replaced names it. Save it first, or pass keepCurrent: true to keep it open beside the new one.

doc.open

Open a .cocad file, replacing the current document.

Detail

Open a .cocad file, replacing the current document. The file's operations are replayed in order, so the reopened document has the same timeline - undo included - that was saved. Nothing changes unless the whole replay finishes: a file that produces no document leaves the current one exactly as it was. A document saved in an older format version opens unchanged and answers olderFormat true, because the next save will write it in the current one. If the file recorded a fingerprint of the geometry it produced, the replay is checked against it and geometryDigest is present only when that check did not pass, naming the value saved and the value this build computes - null when the check could not be made, which means either that this build computes no fingerprint or that firstFailure is present, because a replay that did not finish produced a different document for a reason already named and comparing it would say the build is at fault when a file is simply missing. Opening a file writes a .lock beside it so a second CoCAD - another window here, or another machine on the same share - is told rather than left to overwrite it: readOnly says whether this open got the lock, and lockedBy names who has it (null when nobody could be named, which includes a lock file CoCAD did not write). A read-only document can still be measured, exported and copied from, and saving it writes beside the original rather than over it. The lock is given up when the document is closed or replaced, or when this core exits; one left behind by a crash on this machine is taken silently by the next open.

doc.pack

Copy this document and every part it links to into one folder, with the copied recipe pointing at the copies - so the whole assembly can be sent to somebody else, or moved to another drive, and still open.

Detail

Copy this document and every part it links to into one folder, with the copied recipe pointing at the copies - so the whole assembly can be sent to somebody else, or moved to another drive, and still open. path names the .cocad to write and its folder is where everything lands; each linked part is copied beside it under its own filename, and the copy's recipe stores that bare filename, which means beside this file on any machine. Parts linked by those parts are copied too, and their recipes are pointed at the copies in the same way, so a two-deep assembly arrives whole. A part linked twice is copied once. Two different parts that happen to share a filename get a -2, -3 suffix, because one folder cannot hold both names. It COPIES and never moves: the originals are left exactly where they are, and this document goes on reading them - a pack is not a save, so it does not change which file this document belongs to, does not clear unsaved changes and does not appear in your recent files. Lock sidecars and .bak files are not copied: a lock describes the machine you are on and a backup is a history that is not travelling. If any linked file is missing the whole pack is refused and nothing is written, because a folder with a part missing from it is worse than no folder at all - call query.links first to see what a document needs. Packing where files of the same names already exist is refused too, unless overwrite is true.

doc.recover

Rebuild the document from a crashed session's recording, replacing the current document.

Detail

Rebuild the document from a crashed session's recording, replacing the current document. The recorded commands are replayed in order, exactly as doc.open replays a saved file, so the recovered document has the same timeline - undo included - that was lost. Nothing changes unless the replay produces a document. The recording is left where it is: it is still the only copy until the recovered document is saved.

doc.redo

Re-apply the change undo last reversed, restoring its original entity IDs.

Detail

Re-apply the change undo last reversed, restoring its original entity IDs.

doc.rename

Give a body, a sketch, a construction plane, a construction axis, a construction point, a coordinate system, a reference mesh, a canvas, a component, a joint, a rigid group, an explode state, a section state, a named view, a browser folder, a timeline group, a drawing or a drawing sheet a new display name.

Detail

Give a body, a sketch, a construction plane, a construction axis, a construction point, a coordinate system, a reference mesh, a canvas, a component, a joint, a rigid group, an explode state, a section state, a named view, a browser folder, a timeline group, a drawing or a drawing sheet a new display name. Renaming a component relabels every placement of it at once. Names are what the browser shows and what a find-in-model search reads; they are NOT identity, so they need not be unique and renaming breaks no reference. Undoable.

doc.save

Write the current document to a .cocad file.

Detail

Write the current document to a .cocad file. A .cocad is the document's operation log - the ordered list of commands that built it - under a version header, so it is readable text and opening it replays them. Saving changes nothing about the document and can be done from any state, including a half-drawn sketch. Overwriting an existing file keeps its previous contents beside it as a stamped .bak, the newest files.backupCount of them (5 by default, 0 to keep none); each one is a complete .cocad that doc.open will open. The file also records a fingerprint of the geometry the log produced, so a later build can say whether replaying it reproduced this model exactly. When this document was opened from a file whose fingerprint this build did not reproduce, geometryDigest is present on the first save that follows, naming the value that file recorded and the value this build computed - the save succeeds and records the new geometry as canonical. Saving over a document another CoCAD has open writes your work beside it under a stamped name rather than over theirs, and says so in message; a save is never refused because somebody else has the file, so read path back for where the bytes actually landed. A document is named by its file: after a save it is called the file's name without its extension, and name in the reply says so.

doc.set_appearance

Say what bodies, faces and component instances LOOK like - a colour as r, g and b fractions between 0 and 1.

Detail

Say what bodies, faces and component instances LOOK like - a colour as r, g and b fractions between 0 and 1. Send null to clear, and a cleared face draws at its body's colour, then its material's own look, then the default. This is what somebody CHOSE for this entity, which is a different fact from what the body is made of (ADR 0324): painting a bracket red changes nothing about what it weighs, and doc.set_material is the other half. A placement's colour is that placement's own, so two copies of one part can differ. Undoable, and it changes no geometry - a colour is never a shape. For see-through use doc.set_opacity: there is no alpha here.

doc.set_canvas_frame

Move, turn, flip, recalibrate or re-plane a canvas - the whole placement in one command, absolute values only.

Detail

Move, turn, flip, recalibrate or re-plane a canvas - the whole placement in one command, absolute values only. Send the canvas and any of mmPerPixel, origin, rotation, flip and support; at least one, and absent fields are left exactly as they are, so a retry is safe and nothing here is ever a nudge. mmPerPixel is what the Calibrate gesture sends after two points and a typed distance, and the reply's calibration field then reads sent. Recalibrating rescales the picture about the image's CENTRE, so the traced half stays under its sketch. Journaled and undoable, minting no feature - a canvas is not in the recipe.

doc.set_material

Say what bodies are MADE OF - a name and a density in g/cm3, optionally the appearance that material came with.

Detail

Say what bodies are MADE OF - a name and a density in g/cm3, optionally the appearance that material came with. Send a query.materials row verbatim, or your own numbers; send null to clear. The numbers are stored on the body, never a reference to the library (ADR 0324), so a saved model's mass can never change because a machine's material table did. Bodies only: density is a property of the stuff, and a face has none of its own. query.mass_properties uses what is assigned here, and query.tree discloses it, the appearance included; a body with no colour of its own draws in its material's. Undoable, and it changes no geometry - a material is never a shape.

doc.set_metadata

Write the part-metadata record a BOM row and a title block read - part number, description, material and revision, an exclude-from-BOM flag, and custom fields for what a schema cannot foresee (supplier, finish, coating).

Detail

Write the part-metadata record a BOM row and a title block read - part number, description, material and revision, an exclude-from-BOM flag, and custom fields for what a schema cannot foresee (supplier, finish, coating). Name a component definition ("cp:1") to write its record, or leave entity out to write the document's own - a part file's part IS the document, so that record is what a title block reads for a part drawing. Occurrences and bodies carry no record: every placement of a part answers its definition's, which is what makes a parts list one row per part. An upsert per field: a field left out is untouched, a field sent as null is cleared, and what you send is stored exactly as sent - so a forgotten field is never an erased value and a retry is safe. Values are one line each; mass is deliberately not a field, because mass is derived from the geometry and a typed mass beside a computed one is two places the same fact lives. Undoable, and not a timeline feature: editing a property creates nothing.

doc.set_opacity

How opaque bodies draw, as a fraction in (0, 1] - 1 is opaque, smaller is more see-through.

Detail

How opaque bodies draw, as a fraction in (0, 1] - 1 is opaque, smaller is more see-through. Sets rather than toggles, so sending the same call twice is not two different requests. Display only: nothing about the geometry, measurement or export moves, and it is NOT undoable - the control that set it is its own undo. An opacity of 0 is refused: a body nobody can see is a hidden one, and doc.set_visible is how to say that.

doc.set_sheet_metal_rule

Say what bodies are FOLDED BY - a thickness, the inside bend radius, the K-factor and the bend relief.

Detail

Say what bodies are FOLDED BY - a thickness, the inside bend radius, the K-factor and the bend relief. Send a query.sheet_metal_rules row verbatim, or your own numbers; send null to clear. Assigning a rule is what makes a body sheet metal and clearing it is what stops it being, so there is no separate flag (ADR 0429), and a body with no rule is not sheet metal at some default thickness - it is a body nobody has said is sheet metal. The numbers are stored on the body, never a reference to the table (ADR 0427), so a saved model's flat pattern can never change because a machine's rule table did. Bodies only: a thickness is a property of the stock, and a face has none of its own. One rule per body, because a second flange folds the same sheet as the first. query.tree discloses it. Undoable. A part its own base or contour flange made is RE-FOLDED at the new rule: that flange's rule is rewritten and the part rebuilt from its recipe, so every bend after it follows the new stock, and refolded names the flange - one such part per call, and never in a group. Any other body's rule is a record and moves no geometry.

doc.set_step

Move the document to the state it was in just after a chosen step.

Detail

Move the document to the state it was in just after a chosen step. Steps after it become the redo tail; step 0 is the empty document.

doc.set_units

Change the unit this document's lengths are shown in and typed in.

Detail

Change the unit this document's lengths are shown in and typed in. Storage is always millimetres, so nothing about the geometry moves - only how a number is written for a person and read back from them. Not undoable: it is a way of reading the drawing, not a change to it.

doc.set_visible

Show or hide bodies, sketches, construction planes, construction axes, construction points, coordinate systems, reference meshes, canvases and the three base planes.

Detail

Show or hide bodies, sketches, construction planes, construction axes, construction points, coordinate systems, reference meshes, canvases and the three base planes. Sets rather than toggles, so sending the same call twice is not two different requests. Hiding changes nothing about the geometry, and it is NOT undoable - the browser's eye is its own undo.

doc.switch_branch

Open one of this document's branches in place of the one that is open: its recipe is replayed in order, exactly as doc.open replays a file, so the part, its timeline and its undo history become that branch's.

Detail

Open one of this document's branches in place of the one that is open: its recipe is replayed in order, exactly as doc.open replays a file, so the part, its timeline and its undo history become that branch's. The branch you leave is kept as it stood, rollback marker included, and the document keeps its name, its file and its tab. Nothing changes unless the replay produces a document; a replay that did not finish is reported in firstFailure and the branch's recipe is kept whole, so a later save loses nothing. Switching to the branch already open answers changed false. Not a step and not undoable - switch back to reverse it; doc.undo after a switch undoes that branch's own newest step. A feature made after a switch takes a number no branch of this document has, so features keep their identity across branches.

doc.undo

Reverse the most recent change.

Detail

Reverse the most recent change. Refuses a step another client made unless confirm is true.

Sketching

The constrained 2D sketcher: drawing, constraints and dimensions, and editing that keeps what you built.

sketch.break

Split a sketch curve, keeping every piece.

Detail

Split a sketch curve, keeping every piece. This is sketch.trim that throws nothing away. By default the split lands at the crossing nearest the point you give; set where to "point" to split exactly where your point falls on the curve, whether or not anything crosses there; set where to "all" to split at EVERY crossing at once, which takes no point at all and answers one piece more than there were crossings. The curve you name is deleted and ALL the pieces are NEW curves with new IDs — a break never keeps the old ID, because there is no non-arbitrary answer to which piece would have inherited it — and every constraint that named it goes with it and is listed in the reply. Lines and arcs only: a circle split at one point is still one curve, so use sketch.trim to open one. Set preview true to be shown the pieces without changing anything.

sketch.centerline

Mark sketch lines as centerlines, or stop them being centerlines.

Detail

Mark sketch lines as centerlines, or stop them being centerlines. A centerline is an axis: it is what a revolve turns about, what a mirror reflects across, and what a diameter dimension is measured from. Only a line can be one, and a centerline is always construction geometry — so making a line a centerline also makes it construction. Sets an explicit value rather than toggling, and a call that moves no flag records no history step and emits no event.

sketch.chamfer

Cut the corner off between two sketch curves with a straight line.

Detail

Cut the corner off between two sketch curves with a straight line. Both curves KEEP their IDs and every constraint on them — a chamfer pulls one endpoint of each back along itself from the corner and adds the line between them, so nothing is deleted and nothing is renumbered — with ONE exception: every constraint on either of those two endpoints (the corner's coincident, a lock or a dimension on it) is retired (removedConstraintIds), because the corner it described is now the chamfer line, and that line arrives held in its place — coincident at each end (constraintIds), so the next solve keeps the chamfer rather than pulling the corner back. Give one point on each curve, on the side you want to KEEP; the points also choose which corner gets cut when the curves cross more than once. Sizes are given as two setbacks, one per curve, measured from the corner along that curve — send the same number twice for an equal chamfer. A chamfer only ever shortens: if the two curves stop so far short of their corner that the setback would land past the end of one, extend it with sketch.extend first. Lines and arcs only. Set preview true to be shown the result without changing anything.

sketch.constrain solver

Add constraints and dimensions to a sketch and solve it.

Detail

Add constraints and dimensions to a sketch and solve it. Reports status, remaining degrees of freedom, conflicts and reference readouts. Where a constraint names several things, the LAST point it names is the one that moves to meet the rest (the last curve, when it names no point) — a point goes to its curve, an offset copy to its source, the second of two coincident points to the first — and everything else it names stays where it is whenever the sketch allows that; only when the mover cannot move (it is locked, or held by other constraints) does the rest give way.

sketch.construction

Make sketch curves construction geometry, or make them normal again.

Detail

Make sketch curves construction geometry, or make them normal again. Construction curves are real to the solver and to constraints, and invisible to query.profiles and to the model. Sets an explicit value rather than toggling, so sending the same call twice leaves the sketch where the first one did - and the second call records no history step and emits no event, so a retry costs nobody a Ctrl+Z press. changed names the curves whose flag really moved, and the step's label counts those rather than the request.

sketch.delete

Delete sketch curves.

Detail

Delete sketch curves. Every constraint that names a deleted curve goes with it and is listed in the reply — a constraint whose operand has gone cannot be solved and cannot be repaired. Curve IDs are minted and never reused, so the curves left behind keep the IDs they already had and a deleted curve's ID resolves to nothing from here on. Undo restores the curves, the constraints and the identical IDs.

sketch.draw

Add curves and shapes to a sketch, in one batch.

Detail

Add curves and shapes to a sketch, in one batch. Either every entry is added or none is. A shape — rectangle, polygon, slot, text — becomes its curves plus the constraints that hold it that shape; entities says which curves and constraints each entry produced.

sketch.edit_spline

Change a fit-point spline that already exists, keeping its ID and every constraint on it.

Detail

Change a fit-point spline that already exists, keeping its ID and every constraint on it. Today that means its tangent handles: fitTangents is the WHOLE list afterwards, so send the handles you want and leave out the ones you do not — an empty list clears them all. The curve is re-interpolated through the fit points it has NOW (where query.sketch reports them), and comes out exactly as sketch.draw would draw it from those points and those handles. Its ends do not move. A list equal to the one it already has changes nothing and says changed false. Only a fit-point spline: a control-point spline is shaped by its poles and has no fit points to hold a handle. Set preview true to be shown the result without committing it.

sketch.extend

Lengthen one end of a sketch curve until it meets the next curve in its way.

Detail

Lengthen one end of a sketch curve until it meets the next curve in its way. Give a point beside the end you want moved — the nearer end of the curve is the one that grows — and it runs on along its own straight line, or round its own circle, to the first crossing beyond it. UNLIKE sketch.trim the curve keeps its ID and keeps every constraint on it: one endpoint moves and nothing else about the curve changes. Lines and arcs only, because a circle has no end to move; anything that could be trimmed can be reached, and an ellipse or a spline that might have been in the way is listed in ignoredCurveIds rather than silently treated as absent. When nothing lies beyond that end you are told so and nothing changes — there is no honest distance to extend by. Set preview true to be shown the result without committing it.

sketch.fillet

Round the corner between two sketch curves with an arc of the radius you give.

Detail

Round the corner between two sketch curves with an arc of the radius you give. Both curves KEEP their IDs and every constraint on them — a fillet pulls one endpoint of each back to where the arc meets it and adds the arc, so nothing is deleted and nothing is renumbered — with ONE exception: every constraint on either of those two endpoints (the corner's coincident, a lock or a dimension on it) is retired (removedConstraintIds), because the corner it described is now the arc, and the arc arrives held in its place — coincident and tangent at each end (constraintIds), so the next solve keeps the fillet rather than pulling the corner back. Give one point on each curve, on the side you want to KEEP; the points also choose which of the corners gets rounded when the curves cross more than once. A fillet only ever shortens: if the two curves stop short of their corner, extend them to meet with sketch.extend first. Lines and arcs only. Set preview true to be shown the result without changing anything.

sketch.mirror

Copy sketch curves reflected across a line in the same sketch.

Detail

Copy sketch curves reflected across a line in the same sketch. The copies keep the construction and centerline flags of the curves they came from, and they carry no constraints — to make the copy move with the original, follow this call with sketch.constrain symmetric, passing the same group so the two are one undo.

sketch.move

Move sketch curves where they stand, under one transform — sliding them (type translate), turning them about a point (type rotate) or resizing them about a point (type scale).

Detail

Move sketch curves where they stand, under one transform — sliding them (type translate), turning them about a point (type rotate) or resizing them about a point (type scale). UNLIKE sketch.pattern nothing is copied and nothing is created: each curve you name keeps its ID, its construction and centerline flags, and every constraint on it, and only its shape and position change. Every kind of curve can be moved, because a rigid motion and a uniform scale each map one exactly onto a curve of the same kind. Nothing is re-solved, but a constraint the motion has re-spelled is carried so it stays true of the moved geometry (rewrittenConstraintIds, same IDs): a rotate by a quarter turn swaps horizontal and vertical, any other turn rewrites either as the line's own angle at its new bearing and turns a one-line angle with it; lockX and lockY follow their point under every motion; a scale multiplies every distance, radius, diameter, minorRadius and offset wholly on the moved curves by the factor. A constraint between a moved curve and one that stayed is left alone for the solver to reconcile on the next sketch.constrain. Set preview true to be shown the result without committing it.

sketch.new

Create an empty sketch on a base plane, a planar face or a construction plane.

Detail

Create an empty sketch on a base plane, a planar face or a construction plane. Returns its ID; draw into it with sketch.draw.

sketch.offset

Copy sketch curves at a fixed distance from the ones they came from — lines, circles and arcs only.

Detail

Copy sketch curves at a fixed distance from the ones they came from — lines, circles and arcs only. distance is signed: positive is to the left of the curve's own direction of travel, so a positive offset of a circle or an arc — which always run counter-clockwise — makes a smaller one. Each curve is offset on its own: the copies are not joined to each other and no corners are trimmed. The copies keep the construction and centerline flags of the curves they came from, and they carry no constraints — to make a copy move with its original, follow this call with sketch.constrain offset, the one constraint kind that relates a curve to the copy this command made of it, passing the same group so the two are one undo. Set preview true to be told what the copies would be without making them.

sketch.pattern

Repeat sketch curves under one rigid motion — in a line (type rectangular), about a point (type circular), or along a run of curves (type path, spaced by arc length, each copy carried on the path's own frame or kept parallel with orientation fixed).

Detail

Repeat sketch curves under one rigid motion — in a line (type rectangular), about a point (type circular), or along a run of curves (type path, spaced by arc length, each copy carried on the path's own frame or kept parallel with orientation fixed). count includes the original, so count 4 makes three copies of each curve. spacing and angle are the step between ADJACENT instances: for equal spacing over a total, divide the total by count minus 1; for a full circle, divide 360 by count. A grid is two calls — pattern along one direction, then select the originals and the copies together and pattern that along the other. Every kind of curve can be patterned. The copies keep the construction and centerline flags of the curves they came from, and they carry no constraints. skipInstances leaves individual copies out without moving the ones that stay. Set preview true to be told what the copies would be without making them.

sketch.project kernel

Copy edges and face outlines of the model into a sketch, projected straight down onto that sketch's own plane.

Detail

Copy edges and face outlines of the model into a sketch, projected straight down onto that sketch's own plane. The curves that arrive are ordinary sketch curves — they bound profiles, take constraints and can be extruded — but they are LINKED to what they came from: they cannot be moved, trimmed, extended, filleted or chamfered, and the solver treats them as fixed, so a constraint between a projected curve and a drawn one moves the drawn one. Name an edge ("eg:1.3"), a face ("fc:1.2", which projects its whole boundary, holes included), a curve of ANOTHER sketch ("cu:2.4" — one curve, any kind, including a point or a centreline) or a whole body ("bd:1", which projects its SILHOUETTE — the curves where the solid turns away from this sketch's own direction; a body that turns away nowhere, seen straight down a shaft, has none and is REFUSED, batch and all — project the rim edges you can see instead). Either every reference projects or none does.

sketch.reattach

Re-point a sketch at another base plane, planar face or construction plane.

Detail

Re-point a sketch at another base plane, planar face or construction plane. This is the repair for a sketch whose supportIssue says its face was split or consumed: pass one of the candidates it names. The drawing travels rigidly to the new support: nothing is re-fitted and nothing is renumbered, so every curve, constraint and ID it holds is kept. Re-pointing at the support the sketch already has changes nothing and records no history step.

sketch.section kernel

Cut bodies with a sketch's own plane and put the outline of the cut into that sketch.

Detail

Cut bodies with a sketch's own plane and put the outline of the cut into that sketch. Where sketch.project copies geometry that lives somewhere else — an edge, a face's boundary, a body's silhouette — this answers the shape of the MATERIAL at the plane: section a shaft square to its axis and you get its circle, section it obliquely and you get an ellipse, section a box across and you get its rectangle. Use it to draw something that has to fit what is already there — a gasket, a cover, a rib. The curves that arrive are ordinary sketch curves and are LINKED to the body they were cut from, exactly as a projection is: they cannot be moved, trimmed, extended, filleted or chamfered until sketch.unlink breaks the link. Either every body sections or none does.

sketch.set_constraint solver

Edit dimensions in place: change the number a dimension demands, or flip it between driving (drives the geometry) and driven (a reference readout), keeping its constraint ID.

Detail

Edit dimensions in place: change the number a dimension demands, or flip it between driving (drives the geometry) and driven (a reference readout), keeping its constraint ID. Only a dimension can be edited — a geometric constraint has no value; to change what it relates, remove it with sketch.unconstrain and add the constraint you mean. An entry describes the end state: driving with no value pins the dimension at its current measurement, and a value on a driven dimension is refused because a reference dimension's number is a readout. All edits apply atomically, then the sketch is solved once and the reply reports the solve.

sketch.trim

Cut a piece out of a sketch curve where other curves cross it.

Detail

Cut a piece out of a sketch curve where other curves cross it. Give a point beside the piece you want gone and that piece is removed back to the nearest crossing on each side; when nothing crosses the curve the whole of it goes. The curve you name is deleted and each surviving piece is a NEW curve with a new ID — trimming never keeps the old ID, because there is no non-arbitrary answer to which half would have inherited it. Every constraint that named the trimmed curve goes with it and is listed in the reply. Lines, circles and arcs only, and only those can do the cutting: an ellipse or a spline in the sketch is listed in ignoredCurveIds rather than silently treated as absent. Set preview true to be told what would go and what would be left without changing anything.

sketch.unconstrain

Remove constraints from a sketch.

Detail

Remove constraints from a sketch. Nothing else changes: every curve a removed constraint named keeps its ID, its position and its other constraints, and the geometry does not spring back to where it was drawn — what a removal buys is a degree of freedom, not a previous shape. Use it to relax geometry that inference or a shape constrained for you: a rectangle is drawn with the constraints that keep it rectangular, and removing them is how it becomes a trapezoid. Constraint IDs are minted and never reused, so a removed one resolves to nothing from here on. Undo restores the constraints and the identical IDs. This does not re-solve the sketch, so query.sketch reports dof and fullyConstrained as null until something does.

Break the link between projected sketch curves and the model geometry they came from.

Detail

Break the link between projected sketch curves and the model geometry they came from. The curves stay exactly where they are and keep their IDs, their constraints and their flags — what they lose is the reference, so they become ordinary drawn curves that can be moved, trimmed, extended, filleted and chamfered, and the solver may move them like any other geometry. Use it when a projection has served its purpose as a starting point and the shape should now be free to differ from the model. This cannot be undone by re-running it: relinking means projecting again with sketch.project. Naming a curve that was never projected is not an error — it is already unlinked, and changed reports what really moved. A call that unlinks nothing records no history step and emits no event.

Solid features

Turning sketches into solids and editing the solids: extrudes, revolves, fillets, shells, mirrors and booleans.

feature.align kernel

Move one part so a chosen face of it mates with a face somewhere else - assembly.create_joint's positioning arithmetic as a plain move, with nothing recorded.

Detail

Move one part so a chosen face of it mates with a face somewhere else - assembly.create_joint's positioning arithmetic as a plain move, with nothing recorded. Name what moves (moving: a component placement, which travels as a unit exactly as feature.move's occurrences arm moves it, welded co-members and everything jointed below it included - or one body, which travels alone), the face on it to mate (movingFace), and the face to mate it to (targetFace). A flat face gives its centre and outward normal, a cylindrical one gives its axis at mid-height - so dropping a pin into a bore or a bracket onto a plate is one call each. With no flip the two faces end up facing the SAME way, exactly as an unflipped joint lands its child; send flip to turn the part over first, which is what you want for a face-to-face mate. offset backs it away in millimetres measured in the target face's own axes (z is out of the face), and angle turns it about the mate axis. Everything feature.move promises holds here: nothing is copied, every fc:, eg: and vx: survives, overlap is ordinary, a grounded placement is refused, and it is one undoable feature in the timeline. Unlike a joint, nothing is remembered - the parts are placed and left free - so follow with assembly.create_joint asBuilt if you want the assembly to hold them there. A part already exactly where it was asked to go is a success that records nothing: featureId answers null and no step enters the timeline, so a retry is quiet as well as safe.

feature.base_flange kernel

Make the FIRST wall of a sheet-metal part: a closed sketch profile becomes a flat body as thick as the stock you name, and that body is sheet metal from the moment it exists.

Detail

Make the FIRST wall of a sheet-metal part: a closed sketch profile becomes a flat body as thick as the stock you name, and that body is sheet metal from the moment it exists. Name the region with profile (query.profiles lists them) and the stock with rule - a query.sheet_metal_rules row works verbatim, and its thickness is the wall's thickness, which is why there is no separate thickness argument. side says which side of the sketch plane the metal lies on. It always makes a body of its own: a body is folded by ONE rule, so a base flange joined into an existing body would give that body a second thickness and no flat pattern at all - later flanges bend the wall this one makes. The rule goes on the BODY, where query.tree reports it as sheetMetalRule and every fold after this one reads it; doc.set_sheet_metal_rule on this body re-folds the part at another stock by rewriting this feature's rule and rebuilding. A wall with no stock behind it is a plain extrude: use feature.extrude.

feature.bend kernel

Fold a flat wall of a sheet-metal part about a line drawn on it - the cross-brake in a panel, the step in a bracket, any fold that is not at an edge.

Detail

Fold a flat wall of a sheet-metal part about a line drawn on it - the cross-brake in a panel, the step in a bracket, any fold that is not at an edge. Name the wall with face and the line with line (a straight sketch curve lying over that face; query.sketch lists them), and angle says how far it turns, 90 by default. The line is the bend's CENTRE LINE: the flat it consumes straddles it, half each side, and everything on the moving side is carried round on the end of the bend, flanges and holes and all. fixedSide says which side stays put - "left" or "right" of the line, looking at the face you picked from outside and walking the line from its start to its end - and direction says which way the other side goes. The stock, the bend radius and the K-factor come from the BODY's sheet-metal rule; bendRadius and kFactor override them for this bend only, and the thickness is never overridable because one part is cut from one sheet. The metal the line runs through has to be a plain rectangle of that stock - a hole or another wall inside the bend allowance is refused and says so.

feature.boundary_fill kernel

Fill the volume a set of SHEET bodies encloses: the sheets are intersected and every closed cell they bound becomes a new SOLID body.

Detail

Fill the volume a set of SHEET bodies encloses: the sheets are intersected and every closed cell they bound becomes a new SOLID body. The sheets are NOT consumed - a fill uses only the parts of each sheet that bound a cell, so they keep their IDs and their places (feature.stitch is the door that consumes, when sheets should BECOME one body). The largest cell arrives first, named for the first sheet in bodies; keep narrows the answer to the cells CONTAINING the given points - a point on a wall, or inside no cell, is refused rather than guessed. A set that encloses nothing is refused - there is no cell to fill. One closed sheet (a surface revolve's full torus skin, say) is a legitimate set of one.

feature.bridge_cage kernel

Bridge two ends of a SUBDIV (freeform) body's control cage with a tube of new cage faces, so the body gains a HANDLE (two ends on one side of it) or a TUNNEL (two ends on opposite sides).

Detail

Bridge two ends of a SUBDIV (freeform) body's control cage with a tube of new cage faces, so the body gains a HANDLE (two ends on one side of it) or a TUNNEL (two ends on opposite sides). Each end is either cage faces that make one patch - they are deleted, and the tube starts from the edge round them - or the open cage edges all the way round a hole the cage already has (feature.delete_cage makes one). The two ends' edges must have the same number of points: each point of one is joined to the nearest-matching point of the other. The tube is faces long, and between its ends it arches out along the way each end's faces faced - or runs straight through the body when the other end is behind it. The tube's faces are new ids (cf:), listed under faces; the deleted faces' ids are RETIRED. One step, one undo, a timeline feature. Refused, by name: an id that is not a cage face or edge, ends on two bodies, a body that is not a subdiv body, an end that mixes faces and edges, faces whose edge is not one loop or reaches the cage's open rim, edges that are not one loop round a hole, two ends that touch, and ends whose edges have different numbers of points.

feature.chamfer kernel

Cut a flat across the named edges of one body.

Detail

Cut a flat across the named edges of one body. Each edge carries its own setback, and a setback has two sides: distance is measured on one adjacent face and otherDistance on the other, so an asymmetric chamfer is two numbers and a flip is those two numbers swapped. Omit otherDistance for the ordinary symmetric chamfer. The body keeps its ID, its name and its place in the tree — a chamfer edits the body it was given and creates nothing — and every edge named must belong to that one body.

feature.close_corner kernel

Close the open corner between two flanges of a sheet-metal part - the corner of a box where two sides folded up off edges that meet.

Detail

Close the open corner between two flanges of a sheet-metal part - the corner of a box where two sides folded up off edges that meet. Name the two flange ENDS that face each other across the gap with faces (query.tree lists a body's faces; each end is the flat face that closes a flange's section at the corner, and query.measure reports its normal). Each flange's FLAT is carried on along its own fold line until it reaches the other, and the two ends are cut against each other by type: "overlap" carries the first flange over the second's outside face and stops the second short of the first's inside face; "underlap" is the same the other way round; "butt" mitres both at 45 degrees. gap is the air left between the two ends, 0.1 mm by default. The bends are not carried on - two bends that meet would run into each other - so the bend region stays open under the closed corner, as it does in every sheet-metal package. Both ends must belong to one sheet-metal body, must face each other at a right angle, and both flanges must stand square to the wall; anything else is refused and says why.

feature.combine kernel

Combine existing bodies: join, cut or intersect the target with one or more tool bodies, which act as one tool.

Detail

Combine existing bodies: join, cut or intersect the target with one or more tool bodies, which act as one tool. The target keeps its ID, name and appearance — it is the body that survives — and the tools are removed unless keepTools is true. A cut or intersect that leaves the target in disjoint pieces keeps the target's ID on the largest piece by volume and adds the rest as new bodies; a join never splits, so joining two disjoint bodies is how they become one. Mesh bodies (a scan made with body.from_reference_mesh) combine with mesh bodies the same way and stay mesh bodies, provided each one closes up into a solid (feature.repair_mesh first if not); an exact body and a mesh body cannot be combined in one call - convert the exact one first with body.to_mesh.

feature.configuration

Save a named set of parameter values - a configuration such as "Small", "Large" or "M4 version" - so the part can be switched between them.

Detail

Save a named set of parameter values - a configuration such as "Small", "Large" or "M4 version" - so the part can be switched between them. It is a timeline feature that changes no geometry: name is what the configuration is called, unique in the document, and inputs gives the expression it sets for each parameter it names (only those; the others are left alone). Every name must be a parameter of this document, and the parameters with these expressions installed must evaluate, or the write is refused. query.configurations lists every configuration and says which ones match the parameters now; to switch to one, send param.set_many with its inputs. feature.edit changes one; feature.suppress sets it aside. Undoable.

feature.contour_flange kernel

Make a sheet-metal wall that turns corners: an OPEN run of sketch curves becomes a body as thick as the stock you name, with a bend of that stock's radius at every sharp corner, swept length along the sketch plane's normal.

Detail

Make a sheet-metal wall that turns corners: an OPEN run of sketch curves becomes a body as thick as the stock you name, with a bend of that stock's radius at every sharp corner, swept length along the sketch plane's normal. A channel, a hat section or a U-bracket is one call. Name the run with spine (sketch curves from ONE sketch, query.sketch lists them) and the stock with rule - a query.sheet_metal_rules row works verbatim. The order you name the curves in does not matter; a run that branches, has a gap in it, or closes into a loop is refused. The metal sits half either side of the curves you drew, because an open run has no inside for a side to be measured from - so draw the run down the MIDDLE of the metal. A corner between two straight runs is bent for you; an arc you drew tangentially into both its neighbours is carried through as the bend you drew, at your radius. It always makes a body of its own, and that body is sheet metal from the moment it exists: later flanges bend the walls this one makes.

feature.corner_relief kernel

Cut the corner relief where two bend lines of a sheet-metal part cross - the notch a shop makes in the flat before folding, so the two bends have somewhere to go.

Detail

Cut the corner relief where two bend lines of a sheet-metal part cross - the notch a shop makes in the flat before folding, so the two bends have somewhere to go. Name the two flange ENDS that face each other across the corner with faces, exactly as feature.close_corner does (query.tree lists a body's faces; each end is the flat face that closes a flange's section at the corner). The notch is square or round - whichever the body's sheet-metal rule names - and reaches the rule's relief depth back from each fold line, cutting the wall's corner away and setting both flange ends back with it. Send relief to cut a different shape for this corner only. A rule whose relief is a tear cuts nothing and is refused by name. Both ends must belong to one sheet-metal body and must face each other at a right angle across an open corner; anything else is refused and says why.

feature.crease_cage kernel

Crease or smooth edges of a SUBDIV (freeform) body's control cage.

Detail

Crease or smooth edges of a SUBDIV (freeform) body's control cage. A creased edge stays sharp in the smooth surface - the surface folds along it, so a freeform part can have a hard edge, a seam or a flat-bottomed base - and sharpness 0 smooths a creased edge again (an uncrease). Between 0 and 10 the crease is soft: sharp for that many subdivision levels, then rounding off. Every other edge keeps the sharpness it had, and no face, point or id moves. On a body with a symmetry (feature.symmetry_cage) each edge's partners - its mirror image, or its copies round the axis - get the same sharpness, listed under followed. One step, one undo, a timeline feature; when every edge named already has that sharpness, nothing is recorded and the reply says so (changed is empty). Refused, by name: an id that is not a cage edge, edges of two bodies, a body that is not a subdiv body, an edge the cage no longer has, an edge on the cage's open rim (always sharp), and a soft crease sharp for more levels than the cage can be drawn at (the refusal names the largest that fits).

feature.decimate_mesh kernel

Reduce a MESH body's triangle count where it stands, keeping its shape - the step that makes a dense scan light enough to work with.

Detail

Reduce a MESH body's triangle count where it stands, keeping its shape - the step that makes a dense scan light enough to work with. Edges are collapsed cheapest first by how far each collapse would move the surface (quadric error), so flat regions melt to the few triangles their outline needs while creases and corners are kept. Give the size as targetTriangles or as ratio (the fraction to keep), exactly one. Corners on an open edge or on an edge a repair would call faulty are never moved, so a hole keeps its rim and a fault is left for feature.repair_mesh; no collapse is made that would fold the surface or change whether it closes, so a closed scan stays closed. The target is a ceiling and the reply says whether it was reached. The body keeps its ID, name, material and appearance, and one undo takes the decimation back. If nothing could be collapsed the reply says changed false and NOTHING is recorded. An exact body is refused.

feature.delete_cage kernel

Delete faces of a SUBDIV (freeform) body's control cage, leaving a HOLE: the faces round it keep their shape and their ids, and the edges of the hole become the cage's open rim (the smooth surface ends there), listed under rim - a closed body becomes an open one, as a Freeform Plane is.

Detail

Delete faces of a SUBDIV (freeform) body's control cage, leaving a HOLE: the faces round it keep their shape and their ids, and the edges of the hole become the cage's open rim (the smooth surface ends there), listed under rim - a closed body becomes an open one, as a Freeform Plane is. The way to open a body before bridging two holes into a handle, or to cut away the half of a body you mean to mirror. Every deleted face's id (cf:) is RETIRED and never reused; a cage point no face uses any more is retired too (listed under points). A crease on an edge of the hole goes with it. On a body with a symmetry (feature.symmetry_cage) each face's partners are deleted too, listed under followed - set the symmetry to none first to cut one side away. One step, one undo, a timeline feature. Refused, by name: an id that is not a cage face, faces of two bodies, a body that is not a subdiv body, a face already deleted, every face the cage has (delete the body instead), and a hole that would leave two parts of the cage touching at a point by a corner alone.

feature.delete_face kernel

Remove faces from a SOLID body and heal the openings - the direct edit that defeatures a part.

Detail

Remove faces from a SOLID body and heal the openings - the direct edit that defeatures a part. Name faces of ONE body in faces; the neighbouring faces stretch along their own surfaces to close each opening, so a fillet, a boss or a hole's wall vanishes as if it had never been cut - the natural way to simplify an IMPORTED body that has no feature to suppress (on a native body, feature.suppress is the parametric door and keeps the feature recoverable). No new side wall is ever invented: an opening the neighbours cannot close is refused (a plain box's Top has nothing to close it, for example). The body keeps its ID and name; a removal that severs the body keeps every piece, the largest by volume keeping the ID.

feature.dovetail kernel

Join two pieces of a part with a sliding dovetail: the first piece gains a tail - a wedge-shaped key that widens as it goes - and the second piece takes the matching socket, so the second slides onto the first along one direction and cannot be pulled apart any other way.

Detail

Join two pieces of a part with a sliding dovetail: the first piece gains a tail - a wedge-shaped key that widens as it goes - and the second piece takes the matching socket, so the second slides onto the first along one direction and cannot be pulled apart any other way. The pieces are two exact solids that meet face to face on a plane, as feature.split leaves them; the shared face is found. The key runs straight across the WHOLE shared face along direction (default: the face's long axis), placed where the socket keeps the most wall each side - at least max(1.2 mm, depth / 2), beside it and above it. The tail is the second piece's own material inside the key, moved to the first piece, so its ends follow the part's own outline; the socket is the key grown by clearance on every side. Nothing else is made. Refused, each with details.reason, when the pieces share no flat face (noSharedFace), when the faces do not overlap (noOverlap), when no line across the face has room for the socket and its walls (tooNarrow, with room and needed), when the second piece continues past the face along the slide so it could not slide on (blocked - pass another direction), when it is too thin to hold the socket and its wall (runsOut, with at), and when the socket would cut it in two (severs). One feature, one undo; both bodies keep their IDs. The reply gives the direction used, the key's centre line on the face (line {origin, from, to}, from and to measured along direction), and the tail's width at its root and its widest (topWidth).

feature.dowel kernel

Join two pieces of a part with dowels: drill matching sockets into both pieces across the flat face they share, so they line up when glued or pressed together.

Detail

Join two pieces of a part with dowels: drill matching sockets into both pieces across the flat face they share, so they line up when glued or pressed together. The pieces are two exact solids that meet face to face on a plane, as feature.split leaves them (query.build_fit plans the cuts); the shared face is found, and every face of each piece on that plane counts. Sockets go only where they fit inside both pieces' faces with at least half the dowel's diameter of material round them (never under 1.2 mm) - one dowel where there is most room, two or more spread as far apart as the face allows. Each socket is diameter + 2 x clearance wide and depth deep in each piece. The dowel itself is not made: the reply's dowel {diameter, length} is the pin to print with body.cylinder (it prints best lying down) or to buy - its length is 2 x depth less a clearance at each end. Only material is removed, so both pieces can still print cut face down. Refused when the pieces share no flat face, when the face has no room for a socket, when fewer dowels fit than count asks for (the refusal says how many do), and when a socket would run out of a piece thinner than depth. One feature, one undo; both bodies keep their IDs. Two mesh pieces (a scan split with feature.split) are dowelled the same way, the sockets cut as 48-sided prisms whose flats touch the socket's circle; their reply adds representation, and triangles, volume and closed per body. One mesh and one exact piece are refused.

feature.draft kernel

Taper the named faces of one body about a neutral plane — the draft a moulded or cast part needs so it can leave its tool.

Detail

Taper the named faces of one body about a neutral plane — the draft a moulded or cast part needs so it can leave its tool. Each face carries its own angle, and that angle is the lean the face ENDS UP with rather than an amount added to the lean it already has - so drafting a wall twice at the same angle changes nothing, and a positive angle on a wall that already leans further will take material off. Positive tilts a face so the material grows along the neutral plane's normal and negative shrinks it, and the section where the neutral plane crosses a face keeps its size exactly (a face LYING in the neutral plane has no section to keep and is refused). The body keeps its ID, its name and its place in the tree — a draft edits the body it was given and creates nothing — and every face named must belong to that one body. The taper runs on along any face tangentially continuous with one you name, so a wall joined to its neighbour by a fillet leans the fillet too: draftedFaces in the reply says how many faces were actually leaned. A draft that leans nothing (draftedFaces 0) is a success that records nothing: featureId answers null, no step enters the timeline and no event is emitted, so a retry is quiet as well as safe.

feature.drain_hole kernel

Drill drain holes through the wall of a hollowed body into its sealed void, so resin or powder trapped inside can get out - the step a hollowed part needs before it is printed.

Detail

Drill drain holes through the wall of a hollowed body into its sealed void, so resin or powder trapped inside can get out - the step a hollowed part needs before it is printed. Name the body and, for each hole, a point on the part's OUTSIDE (a point within the hole's radius of the skin is put on the nearest face). Each hole runs along the skin's inward normal there, straight through the wall and half a millimetre into the void, never to the far wall: the wall is measured, so there is no depth to give. A hole must open into the void whole - if its rim would meet the edge of the void rather than open into it, it is refused by position, as is a point whose wall backs onto the outside rather than onto the void. A body with no sealed void is refused: hollow it first with feature.hollow. Holes are measured against the SEALED void, so they go in one call: a body an earlier drain hole already opened is refused naming that feature (undo it and send every hole together). A hollowed MESH body (a scan feature.hollow sealed) is drilled by the same rules; an open or inside-out one is refused naming feature.repair_mesh, and its reply adds representation, triangles, volume and closed. The reply gives each hole's opening, axis and the wall it crossed. One feature, one undo; the body keeps its ID.

feature.edge_flange kernel

Fold a wall off the named edges of a sheet-metal part - the sides of a box, the lip on a bracket.

Detail

Fold a wall off the named edges of a sheet-metal part - the sides of a box, the lip on a bracket. Name the edges with edges (query.edges lists one body's live edge IDs) and how far the flange stands with height, which by default is the FLAT length measured from where the bend ends - heightFrom measures it from the inside or the outside of the wall instead, which is what a drawing dimensions. angle is how far it turns, 90 by default. direction says which way: "up" is toward the side of the wall the edge you picked is on, so picking the top edge of a rim folds upward and picking the bottom edge folds down. The stock and the bend radius come from the BODY's sheet-metal rule - set one with feature.base_flange or doc.set_sheet_metal_rule - and bendRadius overrides it for these bends only; the thickness is never overridable, because one part is cut from one sheet. A flange spans the whole edge unless width says how much of it to span, in which case it is CENTRED on that edge - a tab or a lip rather than a side. A partial flange is NOTCHED at each end with the bend relief the body's rule names, and relief overrides that for these bends only. The bend is added beyond the wall's edge, so the wall itself is not shortened, and every edge named must belong to one body. Two edges that meet at a corner fold into an OPEN corner: the flanges touch along the corner and neither runs into the other.

feature.edit kernel

Change a feature's arguments and rebuild the part from its own recipe.

Detail

Change a feature's arguments and rebuild the part from its own recipe. Everything made after it is re-run against the new shape, so a hole drilled into an extrude moves with it. Send the arguments in full, as query.features reports them - the whole object, never a patch. Nothing changes unless the whole rebuild finishes: a change that breaks a later feature leaves the document exactly as it was and names what refused - the sentence leads with the record that refused ("ft:2 (feature.extrude) refused: ...") and details carries it as failedFeature and failedCommand, so "edit whatever the message names first" is a step, not a search.

feature.emboss kernel

Raise a picture off one face of a body, or sink it in — a logo on a lid, a name round a mug, a part number stamped into a bracket.

Detail

Raise a picture off one face of a body, or sink it in — a logo on a lid, a name round a mug, a part number stamped into a bracket. Draw the picture as closed sketch regions (text included) and name them with profiles; name the face with face; say how far with depth and which way with mode: "emboss" raises it away from the material and joins it on, "deboss" sinks it in and cuts it out. On a FLAT face the sketch's plane must be parallel to the face (the face itself is the usual choice) and the picture is moved straight onto it. On a CYLINDRICAL face — a boss, a pin, or the inside of a bore — the sketch's plane must be parallel to the axis (a plane tangent to the face is the usual choice) and the picture is WRAPPED round it: a width drawn across the axis becomes the same length of arc, a height along the axis stays a height, and the walls stand straight out from the axis. It is centred where the sketch faces the cylinder, may reach up to half a turn either way, and must lie wholly on the named face. The body keeps its ID, name and visibility.

feature.extend kernel

Grow a SHEET body past its boundary.

Detail

Grow a SHEET body past its boundary. Name FREE boundary edges in edges (an edge two faces share is interior and refused) and a distance; each edge is extended by its perpendicular strip - the surface swept from the edge along the sheet's own tangent, straight out. EXACT only: an edge whose perpendicular direction is constant (every edge of an extruded sheet), or a full circle on a flat face (the strip is a concentric band), extends cleanly; an edge with neither closed form is refused whole rather than approximated, because a guess written into the geometry could never be told from the real thing. A strip continuing its own face's surface merges into it seamlessly. The body keeps its ID and its faces keep theirs.

feature.extrude kernel

Sweep closed sketch regions into a solid, along the sketch plane's normal.

Detail

Sweep closed sketch regions into a solid, along the sketch plane's normal. Take the profile IDs from query.profiles. The extent is two ends: end is required and start defaults to the sketch plane itself, and each is decided by a signed distance, by a target to stop at, by the next body in the way, or by going through everything on that side. There is no flip flag — the sign is the direction, and so is the slot. A symmetric extrude of 10 mm is start -5 and end 5; a two-sided one is start -a and end b; one that begins 2 mm off the plane and runs 10 mm is start 2 and end 12; one that goes through everything both ways is through_all in both slots. Every profile must come from the same sketch, and a profile already carries its own holes, so do not name them. operation says what becomes of the swept solid: a body of its own, or joined to / cut from / intersected with the bodies it meets, which keep their IDs and names. A cut or intersect that leaves a body in disjoint pieces keeps its ID on the largest piece by volume and adds the rest as new bodies. thin sweeps only a wall along the profile's boundary rather than its whole area. surface: true sweeps a SURFACE instead of a solid (ADR 0301): the boundary's walls with no caps, answering a SHEET body — sheet: true on the reply and the tree row, and no volume to measure (feature.thicken gives a sheet its thickness and makes it a solid, ADR 0302). Its operand is profiles (one tube-like wall per boundary loop) or curves (an open or closed run of sketch curves from one sketch — a ribbon, or a tube when the run closes), exactly one of the two; both ends must be distances, and operation, thin and taper are refused beside it.

feature.extrude_cage kernel

Extrude faces of a SUBDIV (freeform) body's control cage - the first step of shaping one: the chosen faces move out by distance, and a wall of new cage faces grows from every edge around them, so the smooth surface bulges out into an arm, a leg, a spout.

Detail

Extrude faces of a SUBDIV (freeform) body's control cage - the first step of shaping one: the chosen faces move out by distance, and a wall of new cage faces grows from every edge around them, so the smooth surface bulges out into an arm, a leg, a spout. Faces that share an edge move together as one patch along that patch's own outward direction; faces that do not, each along their own. The extruded faces keep their ids (cf:<body>.<n>), so the same selection can be extruded again; the reply lists the new wall faces under walls. One step, one undo, a timeline feature. Refused, by name: a face that is not a cage face, faces of two bodies, a body that is not a subdiv body, a distance of 0, every face of a closed cage (that would only move the body), faces that point opposite ways, and faces that touch at a point by a corner alone.

feature.fillet kernel

Round the named edges of one body.

Detail

Round the named edges of one body. Each edge carries its own size, so a uniform round is one number repeated and a stepped one costs nothing extra. A round that VARIES along its edge is a stops law instead of a radius — at least two {position, radius} stops, positions running 0 to 1 along the contour — and each edge states exactly one of the two, though different edges in one call may state different ones. The body keeps its ID, its name and its place in the tree — a fillet edits the body it was given and creates nothing — and every edge named must belong to that one body.

feature.finger_joint kernel

Join two plates at a square corner with a finger joint (a box joint): the corner is cut into an odd number of equal fingers that interleave, the first plate taking the two end fingers and every second one between, the second plate keeping the rest - so the two press together like a laser-cut box and both outside faces show the fingers.

Detail

Join two plates at a square corner with a finger joint (a box joint): the corner is cut into an odd number of equal fingers that interleave, the first plate taking the two end fingers and every second one between, the second plate keeping the rest - so the two press together like a laser-cut box and both outside faces show the fingers. The plates are two exact solids where the first's END face lies against the second's SIDE (a butt corner, or a T); the shared face is found. Each finger the first plate gains is the second plate's own material, through its whole thickness, and the second plate's socket is the finger grown by clearance on every side. Give fingers (odd) or fingerWidth, or neither for fingers about twice the second plate's thickness. Nothing else is made. Refused, each with details.reason, when the plates share no flat face (noSharedFace), when the faces do not overlap (noOverlap), when the first's face on the plane is not smaller than the second's - the order is reversed, or the pieces are a plate cut straight across (notACorner), when the shared region is not a full rectangle (notRectangular), when the second plate is not one even thickness behind it (uneven, with at), when a finger would be narrower than 1 mm once the clearance is taken (tooFine, with step and needed), and when the sockets would cut the second plate in two (severs). One feature, one undo; both bodies keep their IDs. The reply gives the direction along the joint, the joint's corner (origin), its length, width and depth (the second plate's thickness), and the fingers and their width.

feature.fit kernel

State what round holes or pins are sized FOR - "this hole is a press fit for a 5 mm pin" - so the fit lives in the model rather than in somebody's head.

Detail

State what round holes or pins are sized FOR - "this hole is a press fit for a 5 mm pin" - so the fit lives in the model rather than in somebody's head. It is a timeline feature that changes no geometry: it records the intent, and query.design_check then judges each named round against it using the fit calibration you name, reporting the diameter the printer is predicted to make, the diameter the fit wants, and suggested - the diameter to DRAW so this machine prints it right. Nothing is ever changed for you: resize the hole yourself (feature.edit on the feature that made it). nominal is the MATING size (the 5 of a 5 mm pin), never read off the drawing, because the drawn size is what you will change to compensate a printer. Give the band as an ISO 286 class in designation ("H7" for a hole, "p6" for a pin; query.fits shows what one means) or as two plain deviations from nominal in lower and upper - an FDM press fit on a hole is typically a little below nominal, a slip fit a little above, and your own printer's numbers are the right ones. Every face must be a round (a cylindrical face that closes on itself) of one body, all holes or all pins - which side a round is on is read off the geometry, never sent. A round carries one fit; feature.edit changes it and feature.suppress switches it off.

feature.flexify kernel

Make a MESH body flexible: cut it along a spine into rigid segments joined by print-in-place ball joints, so a scanned dragon, fish, snake or tentacle prints as one part and moves when it comes off the bed.

Detail

Make a MESH body flexible: cut it along a spine into rigid segments joined by print-in-place ball joints, so a scanned dragon, fish, snake or tentacle prints as one part and moves when it comes off the bed. Joints are spaced pitch apart in a straight line along the spine (path), the first one pitch from its start - or, round a closed spine, evenly round the loop, so a bracelet scan becomes a ring of segments. At each joint the segment before it gets a ball on a neck and the segment after it a hollow socket that holds the ball, clearance all round - body.chain's ball joint, sized by ballDiameter and clearance - and the two are parted by a V-shaped gap that lets the joint turn bend degrees any way from the pose the body was cut in (15 by default, never more than the ball's swing). With joint "hinge" each joint is a knuckle and pin turning in a bored fork instead (sized by pinDiameter), the gap opens in one plane only, and the body bends in that plane - the plane a flat spine lies in. Every joint is checked before anything is cut: the body must have room round it for the socket (refused naming the joint, how much room there is and the largest ball that fits), joints that are not neighbours must not crowd each other (a spine that comes back near itself), and every segment must come out ONE piece - a cut that also passes through a leg or a fin away from the spine would leave it loose, and is refused naming the segment. The body keeps its ID, name, material and appearance and stays a mesh body holding every segment as a separate closed surface, so it exports as one file; one undo takes it back. An exact body is refused - turn it into a mesh with body.to_mesh first. Set preview true to see the plan without cutting.

feature.flip_normal kernel

Reverse which way a SHEET body's surface normals point.

Detail

Reverse which way a SHEET body's surface normals point. The geometry does not move and every face keeps its ID - what changes is what every side word downstream means: feature.thicken's and feature.offset's "front" become the old "back", and a mesh export's winding reverses. The viewport shades sheets from both sides, so the picture looks the same after a flip - that is correct, not a failure; the new feature in query.features is the proof it happened. A solid is refused: its outward normals are what makes it solid.

feature.hem kernel

Fold the edge of a sheet-metal part right back on itself - the safe edge on a panel, the stiffened lip on a tray, the return that hides a raw cut.

Detail

Fold the edge of a sheet-metal part right back on itself - the safe edge on a panel, the stiffened lip on a tray, the return that hides a raw cut. Name the edges with edges (query.edges lists one body's live edge IDs) and how far the return reaches with height, measured back over the wall from the sheet's own edge. A hem is a 180-degree fold, so there is no angle: for any other angle use feature.edge_flange. The GAP between the return and the wall is twice the bend radius, which comes from the BODY's sheet-metal rule - set one with feature.base_flange or doc.set_sheet_metal_rule - and bendRadius overrides it for these bends only, so a 0.5 mm radius is a 1 mm gap. direction says which face the return folds onto: "up" is toward the side of the wall the edge you picked is on. A hem spans the whole edge unless width says how much of it to span, in which case it is CENTRED on that edge, and a partial hem is NOTCHED at each end with the bend relief the body's rule names, which relief overrides. The bend is added beyond the wall's edge, so the wall itself is not shortened. To hem a hem - a double hem - send this command again naming the free edge of the first return.

feature.hole kernel

Drill holes — plain, counterbored or countersunk — at named sketch points, and cut them out of the bodies they meet.

Detail

Drill holes — plain, counterbored or countersunk — at named sketch points, and cut them out of the bodies they meet. The sketch those points belong to is the entry surface: its plane is the one datum every length is measured from and its normal is the axis, so depth's sign is the only direction there is. All the holes act as ONE tool, so a body only some of them reach is still cut by those. A hole only ever removes material, which is why there is no operation to choose.

feature.hollow kernel

Hollow one body out completely, leaving a wall of the given thickness and a sealed void with no way in.

Detail

Hollow one body out completely, leaving a wall of the given thickness and a sealed void with no way in. Nothing is opened: every face of the body keeps its wall. To hollow a body and open it at a face — a cup, a box with a lid off — use feature.shell, which is this command's other half. The body keeps its ID, its name and its place in the tree: a hollow edits the body it was given and creates nothing. A MESH body (a scan, a downloaded or generated model) is hollowed too, all three sides: the new surface is meshed from its distance to the body's triangles, edgeLength apart (half the wall when left out), an inward hollow keeps the outside exactly and leaves any part thinner than twice the wall solid, and a scan that is not closed is refused naming feature.repair_mesh. The void is sealed either way, so a resin or powder print still needs drain holes.

feature.insert_cage_loop kernel

Insert an EDGE LOOP into a SUBDIV (freeform) body's control cage: a new row of cage faces running ACROSS the named edge, so the smooth surface can be shaped there - extruded, creased, pulled - without disturbing it anywhere else, and a loop near an edge holds the surface tighter to it.

Detail

Insert an EDGE LOOP into a SUBDIV (freeform) body's control cage: a new row of cage faces running ACROSS the named edge, so the smooth surface can be shaped there - extruded, creased, pulled - without disturbing it anywhere else, and a loop near an edge holds the surface tighter to it. The loop crosses every four-sided face of the named edge's ring, cutting each in two; it runs all the way round when the ring closes (round a box's waist), and a face where the ring ends that is not four-sided (a sphere's pole triangle) takes the new point as one more corner. Every edge the loop crosses is split, and its id is RETIRED - never reused (the reply lists them under split); the new edges are numbered after every edge that already was, the loop's own listed under loopEdges. Every face keeps its id - the half of each cut face on the side of the named edge's first point keeps it, and the other half is added (under faces). A crease on a split edge stays on both halves. One step, one undo, a timeline feature. Refused, by name: an id that is not a cage edge, edges of two bodies, a body that is not a subdiv body, an edge the cage no longer has, an edge with no four-sided face on either side, a ring that would cross one face twice, and a cut that would leave a soft crease too deep to draw.

feature.jog kernel

Step a flat wall of a sheet-metal part sideways about a line drawn on it - the offset in a bracket, the lap in a panel, any place one part of a wall has to sit parallel to the rest and a fixed distance off it.

Detail

Step a flat wall of a sheet-metal part sideways about a line drawn on it - the offset in a bracket, the lap in a panel, any place one part of a wall has to sit parallel to the rest and a fixed distance off it. Name the wall with face and the line with line (a straight sketch curve lying over that face; query.sketch lists them), and height says how far the moving side steps. It is TWO bends: one turns the metal off the wall by angle, a flat run carries it across, and the second turns it back, so the moving side ends up parallel to the wall it came from. The line is the jog's CENTRE LINE and the flat it consumes straddles it. fixedSide says which side stays put - "left" or "right" of the line, looking at the face you picked from outside and walking the line from its start to its end - and direction says which way the step goes. The stock, the bend radius and the K-factor come from the BODY's sheet-metal rule; bendRadius and kFactor override them for this jog only. The metal the line runs through has to be a plain rectangle of that stock - a hole or another wall inside the strip is refused and says so.

feature.lattice kernel

Turn a MESH body into a decorative, printable strut lattice where it stands: a tube along every edge of its surface (pattern wireframe - triangular cells) or across every edge between the centres of the triangles on either side (pattern voronoi - a six-sided cell round every corner), joined at balls and united into one closed solid.

Detail

Turn a MESH body into a decorative, printable strut lattice where it stands: a tube along every edge of its surface (pattern wireframe - triangular cells) or across every edge between the centres of the triangles on either side (pattern voronoi - a six-sided cell round every corner), joined at balls and united into one closed solid. strutDiameter sets the tubes and nodeDiameter the balls (the struts' own diameter by default). cellSize remeshes the surface to even edges of that length first, so the cells are even and of a size you choose; left out, the surface's own triangles are the cells. An open surface is fine - its rim becomes a strut. Refused before anything is built: more than 10000 struts (naming the cellSize that fits), a node thinner than its struts, and struts so thick they close every cell (naming the cellSize that leaves openings). The body keeps its ID, name, material and appearance and stays a mesh body; one undo takes the lattice back. An exact body is refused - turn it into a mesh with body.to_mesh first. Set preview true to see the plan without building.

feature.living_hinge kernel

Join two pieces that share a flat face with a living hinge: the face is opened length wide (default 2 mm), taken from the second piece, everywhere but a thin web thickness thick (default 0.4 mm) along one edge of the face - so the two fold about that edge and stay ONE part, printed flat in one go.

Detail

Join two pieces that share a flat face with a living hinge: the face is opened length wide (default 2 mm), taken from the second piece, everywhere but a thin web thickness thick (default 0.4 mm) along one edge of the face - so the two fold about that edge and stay ONE part, printed flat in one go. The edge (edgeId) is a straight edge of either piece on the rim of the face they share, where both pieces end; the web runs its whole length, inside the face. The first piece keeps its shape and its ID and gains the second, whose ID retires (removedBodyIds). The reply reports the web's surface strain when folded flat, pi x thickness / (2 x length) (0.3 is 30%), as a number and never a verdict: polypropylene and PETG take a high one, PLA cracks - compare it with the material's. Refused, each with details.reason, when the pieces share no flat face (noSharedFace), when the edge is not on the shared face's rim (notOnRim), when the web would not lie wholly on both faces (offFace, with at), when the second piece is not deeper behind the face than length (runsOut, with depth) and when the opening would cut it in two (severs); a curved edge, or one of a third body, by name. One feature, one undo. The reply gives the hinge's axis (direction) and the web's run along it (from, to), the shared plane, and the strain.

feature.loft kernel

Make a solid that passes through two or more closed sketch regions in the order you name them — a boat hull, a transition duct, a blended handle.

Detail

Make a solid that passes through two or more closed sketch regions in the order you name them — a boat hull, a transition duct, a blended handle. Take each section ID from query.profiles. THE ORDER MATTERS and it is yours: the solid runs from the first section in the list to the last, which is why there is no flip flag, and the sections do not have to march along any one axis — a loft that doubles back on itself is spelled by naming the sections in the order it visits them. Unlike an extrude or a revolve, the sections may come from DIFFERENT sketches, which is the ordinary way a loft is drawn: one profile per plane. The first and last entries may be a POINT rather than a region — a body corner, a construction point or a sketch point — which runs the solid to a tip: a square and a point above it make a pyramid, and a point at each end of one section makes a spindle. centerline names a run of sketch curves — or of edges of one body you already have — that the material travels along, so the solid bends between its sections instead of running straight from one to the next — a swan-neck duct, a curved horn, a handle that sweeps round. guide names a second run beside it — a GUIDE RAIL — that says which way up the sections stay as they travel, so a duct can roll as it bends; it is only meaningful with a centerline. transition says whether the surface is one smooth run through every section or a straight taper between each consecutive pair. closed makes it a RING: the surface carries on from the last section back into the first and the solid has no end caps, which is how a torus-like duct or a handle is made — three sections at least, and never spelled by naming the first section twice. operation says what becomes of the lofted solid: a body of its own, or joined to / cut from / intersected with the bodies it meets, which keep their IDs and names. surface: true lofts a SURFACE instead of a solid (ADR 0301): the skin through the sections with no caps, answering a SHEET body — sheet: true on the reply and the tree row, and no volume to measure until feature.thicken gives it one. The sections, points, closed and transition read exactly as for a solid — a closed skin for a ring, a cone's skin to a tip — and operation and centerline are refused beside it.

feature.match_cage kernel

Match a run of a SUBDIV (freeform) body's open rim to a curve - so a freeform sheet or the edge of a hole meets an exact body's edge or follows a sketch: the named rim points move so that the smooth surface's edge passes through the target at every one of them, keeping the spacing they had along the rim, and the reply's deviation says how far the surface's edge strays from the target between them (more rim points - an edge loop across the rim - tighten it).

Detail

Match a run of a SUBDIV (freeform) body's open rim to a curve - so a freeform sheet or the edge of a hole meets an exact body's edge or follows a sketch: the named rim points move so that the smooth surface's edge passes through the target at every one of them, keeping the spacing they had along the rim, and the reply's deviation says how far the surface's edge strays from the target between them (more rim points - an edge loop across the rim - tighten it). Only the rim's points move, so the surface's slope where it meets the target is whatever its next row of points makes it. A whole rim loop matches a target that closes (a circular edge); a run with two ends matches one with two ends, end to end, whichever way round is nearer. When the body has a symmetry (feature.symmetry_cage) each matched point's partners off the rim follow it, listed under followed. One step, one undo, a timeline feature; every id is kept, and a match that moves nothing records nothing. Refused, by name: an id that is not a cage edge, edges of two bodies or that are not one run, an edge between two faces (only the open rim is matched), a soft crease meeting the rim, a target with a hard corner or no length, and an open run asked to follow a closed target or the reverse.

feature.mirror kernel

Reflect one body in a plane and do something with the image: keep it as a body of its own, or join it to / cut it from / intersect it with the bodies it meets.

Detail

Reflect one body in a plane and do something with the image: keep it as a body of its own, or join it to / cut it from / intersect it with the bodies it meets. The plane is a base plane, a planar face or a construction plane — the same three things a sketch can be drawn on — and the body being mirrored is never modified. There is no geometric refusal: a reflection is an isometry, so a plane straight through the body is fine (the halves swap) and so is the body's own plane of symmetry. A mesh body (a scan made a body) is mirrored too, into a new mesh body whose triangles still face outward; its join, cut and intersect are refused, because combining triangles needs mesh booleans.

feature.move kernel

Move bodies (bodies) or whole component placements (occurrences) where they stand, under one transform -- sliding them (type translate), turning them about an axis (type rotate), or resizing them uniformly (type scale, bodies only).

Detail

Move bodies (bodies) or whole component placements (occurrences) where they stand, under one transform -- sliding them (type translate), turning them about an axis (type rotate), or resizing them uniformly (type scale, bodies only). UNLIKE feature.pattern and feature.mirror nothing is copied and nothing is created: each body you name keeps its ID, its name, its visibility and every face and edge ID on it, and only where it sits changes. So a sketch drawn on one of its faces, a fillet on one of its edges and a construction plane built from it all still refer to the same things afterwards - and the sketch and the plane MOVE WITH the body, carried by the same motion, so a hole sketched on a face is still on that face after the part slides or turns. Every solid can be moved, because a rigid motion maps one exactly onto a solid of the same shape, and there is no geometric refusal at all -- bodies that end up overlapping each other are ordinary, because a move is not a boolean. A scale keeps every ID the same way -- a uniform resize maps each face, edge and vertex one to one -- and is the one motion here that changes size: every length multiplies by factor and the volume by its cube, with center the one point that stays put. The one non-geometric refusal is a body inside a GROUNDED component placement: grounding says a part is fixed in space, so free it with assembly.set_grounded first, or move the other parts around it instead. With occurrences a placement moves as a UNIT -- every body under it, nested sub-assemblies, jointed children and all -- which is how you position an assembly's parts relative to each other; a scale is refused there, because resizing one placement would make it a different SIZE from its siblings -- name its bodies in bodies if that divergence is what you want. To make a COPY somewhere else, use feature.pattern with count 2. A mesh body (a scan made a body with body.from_reference_mesh) moves, turns and resizes the same way: every one of its triangle corners goes through the same transform, it stays a mesh body with the same ID, and nothing is re-meshed.

feature.move_cage kernel

Move points of a SUBDIV (freeform) body's control cage - the way a freeform part is sculpted: the named cage points, edges and faces move under one transform and the smooth surface follows them, bulging where they go out and flattening where they come in.

Detail

Move points of a SUBDIV (freeform) body's control cage - the way a freeform part is sculpted: the named cage points, edges and faces move under one transform and the smooth surface follows them, bulging where they go out and flattening where they come in. translate slides them by delta, rotate turns them about axis by angle, scale moves them toward or away from center by factor (the same arguments feature.move takes for a whole body). Only positions change: every face, edge, crease and id stays as it was, so the same selection can be moved again. When the body has a symmetry (feature.symmetry_cage) every named point's partners move too - the mirror image of the move, or the move turned round the axis - listed under followed, and a point on the mirror plane or the axis stays on it. One step, one undo, a timeline feature; when no point would move (a rotation about an axis through them all, a scale about the one point named) nothing is recorded and moved is empty. Refused, by name: an id that is not a cage point, edge or face, elements of two bodies, a body that is not a subdiv body, a point, edge or face the cage no longer has, a zero or missing motion, and an argument that belongs to another type.

feature.offset kernel

Offset a surface into a NEW sheet body.

Detail

Offset a surface into a NEW sheet body. Name a SHEET body in body to offset its whole surface, or faces of ONE body in faces - a solid's faces work too, which is how a solid's skin becomes a surface to model with. The new sheet lands distance mm along the face normals (side "front", the default) or against them ("back"); the source body is never touched and the answer is always a sheet of its own - feature.thicken gives it material, feature.stitch joins it to other sheets.

feature.paste kernel

Paste bodies copied with query.copy into this document.

Detail

Paste bodies copied with query.copy into this document. Send the content that command answered, unchanged; the bytes are CoCAD's own exact geometry, so a pasted body is identical to the one it was copied from rather than a conversion of it. The bodies join the document you already have rather than replacing it, and arrive at the coordinates they were copied at, as ONE undoable step - move them afterwards with feature.move if you want them somewhere else. Send names to keep what each body was called; omit it and they are named for the body number they get - Paste12 for bd:12, exactly as the twelfth box would be Box12. The bytes are stored in the document, so saving and reopening does not need the document they came from.

feature.patch kernel

Fill a closed boundary with a NEW surface body (ADR 0301 - a sheet, one face).

Detail

Fill a closed boundary with a NEW surface body (ADR 0301 - a sheet, one face). The boundary is exactly one of edges - a sheet body's free boundary edges forming one closed loop, with continuity/continuities saying how the patch meets each edge's owning face (G0 touch, G1 tangent, G2 curvature) - or curves, a closed ring of one sketch's curves (G0 by construction). points and rails add interior constraints the surface passes through and contains. The answer is a new body of its own, born beside the boundary's owner; it is NOT sewn on - feature.stitch joins it when it should become part of the sheet, and a closed set then promotes to a solid.

feature.pattern kernel

Repeat one body (body) or one component placement (occurrence) under a rigid motion — in a line (type rectangular), about an axis (type circular), or along a run of curves (type path, spaced by arc length, each copy carried on the path's own frame or kept parallel with orientation fixed).

Detail

Repeat one body (body) or one component placement (occurrence) under a rigid motion — in a line (type rectangular), about an axis (type circular), or along a run of curves (type path, spaced by arc length, each copy carried on the path's own frame or kept parallel with orientation fixed). count includes the original, so count 4 makes three copies, and what is being patterned is never modified. With body, the copies can be kept as a body of their own or joined to / cut from / intersected with the bodies they meet, and they act as ONE tool, which is what makes a bolt circle of holes a single cut. With occurrence, each copy is another placement of the same component — so a parts list counts one part eight times rather than eight parts — and operation, targets and name do not apply. skipInstances leaves individual copies out without moving the ones that stay, so a row of holes can have a gap in it. There is no geometric refusal: a rigid motion is an isometry, so copies that overlap each other, or the original, are ordinary. A mesh body (a scan made a body) is patterned too, rectangular or circular, into one new mesh body holding the copies; its join, cut and intersect are refused, because combining triangles needs mesh booleans.

feature.press_pull kernel

Press or pull faces of a SOLID body - the direct edit also called offset face.

Detail

Press or pull faces of a SOLID body - the direct edit also called offset face. Name faces of ONE body in faces and a distance in mm; side "front" (the default) moves them along their own normals - a solid's normals point OUT, so front GROWS the body and "back" presses in, removing material. The neighbouring faces stretch or shrink along their own surfaces to stay joined; no new side wall is ever invented, and a press the neighbours cannot close is refused (to add material WITH walls, feature.extrude on the face's profile is the door). The body keeps its ID and name and the pressed faces keep theirs; a press that severs the body keeps every piece, the largest by volume keeping the ID.

feature.project_curve kernel

Project sketch curves straight through a SHEET body and IMPRINT where they land: the sheet's faces split along the projection and the curves become real, nameable edges of the body - the reply's edgeIds, exactly what feature.patch, feature.extend and a draft can then take.

Detail

Project sketch curves straight through a SHEET body and IMPRINT where they land: the sheet's faces split along the projection and the curves become real, nameable edges of the body - the reply's edgeIds, exactly what feature.patch, feature.extend and a draft can then take. The direction is the curves' own sketch plane normal, straight through both ways. The body keeps its ID and loses nothing - feature.trim is the remover. A projection that misses the sheet, or lands only along existing boundaries, is refused: an imprint that changes nothing does not journal. A solid is refused - sketch.project reads model edges INTO a sketch, and the solid split is a later feature on this vocabulary.

feature.rebend kernel

Fold back a bend that feature.unbend opened, so a slot or a hole cut across the flat is carried round the fold with it.

Detail

Fold back a bend that feature.unbend opened, so a slot or a hole cut across the flat is carried round the fold with it. Name the unbend step with feature - its ft: id, from query.features - and nothing else: the angle, the radius, the thickness, the K-factor and the wall that stayed put are all on that step already, and stating any of them again would be a second answer to a question it has answered. A slot that runs right across the flattened bend through the full thickness of the sheet is folded with the metal; a hole inside the bend, or a pocket that does not go through, is refused and says so, because this build carries a cut round a fold only where the cut goes all the way across it. An ft: that is not a feature.unbend, an unbend that is suppressed, and a bend that has already been folded back are each refused by name. Leaving a part unfolded is a perfectly good part; nothing insists you call this.

feature.remesh_mesh kernel

Even out a MESH body's triangles where it stands, keeping its shape - every edge near one length, the way a subdivision cage, a mesh boolean or a clean wireframe wants them.

Detail

Even out a MESH body's triangles where it stands, keeping its shape - every edge near one length, the way a subdivision cage, a mesh boolean or a clean wireframe wants them. Long edges are split, short ones collapsed and edges flipped until each corner has about six neighbours, then every free corner is slid along the surface and put back exactly ON the scan's original surface, so the part does not smooth or drift the way a plain averaging pass would. Every corner is on that surface, but a new triangle's face is a chord: where it spans a fold between the original triangles it cuts across it, so a faceted curve (a scanned or exported cylinder, say) loses a sliver of volume - half a percent on a 48-sided puck evened out at 2 mm. Creases (edges whose triangles meet at creaseAngle or more, 45 degrees by default) are kept exactly. Corners on an open edge or on an edge a repair would call faulty are never moved, so a hole keeps its rim and a fault is left for feature.repair_mesh; nothing is done that would fold the surface or change whether it closes, so a closed scan stays closed. The target length is edgeLength, or the body's own mean edge length when left out, and the reply gives it with the shortest, mean and longest edge before and after. The body keeps its ID, name, material and appearance, and one undo takes the remesh back. If nothing changed the reply says changed false and NOTHING is recorded. An exact body is refused.

feature.reorder kernel

Move a feature earlier or later in the timeline and rebuild the part from its own recipe.

Detail

Move a feature earlier or later in the timeline and rebuild the part from its own recipe. Everything is re-run in the new order, so moving a fillet above the extrude whose edge it rounds is refused and the document does not move. The feature keeps its ft: id and its arguments, and so does every other feature - a reorder renumbers nothing.

feature.repair_mesh kernel

Repair a MESH body's triangles where it stands - the step that makes a real scan printable.

Detail

Repair a MESH body's triangles where it stands - the step that makes a real scan printable. It removes slivers (triangles with two corners in one place) and repeated triangles, turns facets that disagree with their neighbours so the whole surface is wound one way, turns a surface that closes so it faces OUTWARD, and fills holes whose rim is a simple loop with a fan of triangles. Corners at exactly the same coordinates become one corner; nothing is moved, smoothed, decimated or re-meshed. The body keeps its ID, name, material and appearance, and one undo takes the repair back. If nothing needed repairing the reply says changed false and NOTHING is recorded - no timeline step - so it is safe to call on every scan. The reply counts each fix, says how many openings were left and how many edges carry three or more triangles (which no repair here splits), and whether the result now closes up into a solid. An exact body is refused.

feature.require kernel

State a requirement the part must keep meeting - "an M3 passes through this hole", "every wall at least 1.6 mm", "the lid clears the base by 0.5 mm", "fits a 256 mm bed" - as a check CoCAD re-runs against the current model whenever query.requirements is read.

Detail

State a requirement the part must keep meeting - "an M3 passes through this hole", "every wall at least 1.6 mm", "the lid clears the base by 0.5 mm", "fits a 256 mm bed" - as a check CoCAD re-runs against the current model whenever query.requirements is read. It is a timeline feature that changes no geometry: statement is the sentence, and quantity, entities and atLeast/atMost are the check you compiled it into. Six quantities, each measured by the read you would call yourself: diameter of a round (query.measure; "an M3 passes through" is atLeast 3.2, or whatever clearance your shop uses), distance between two things (query.measure's between; "clears by 0.5" is atLeast 0.5), wallThickness of a body (query.wall_thickness), size along an axis (query.build_fit's extent; "fits a 256 mm bed" is two requirements, x and y, atMost 256), volume and mass (query.mass_properties). The reply is the requirement's first check - status pass, fail or unmeasured, the measured number and the read that produced it - so you see at once whether the part already meets it. A requirement may be stated before the part meets it, or before it can be measured at all (a mass before doc.set_material): it is recorded and reported unmeasured with the reason. What is refused is a malformed check and anything the read itself refuses, such as a body that does not exist. Nothing ever refuses because a requirement fails. feature.edit changes one; feature.suppress switches it off.

feature.revolve kernel

Turn a closed sketch region about an axis into a solid.

Detail

Turn a closed sketch region about an axis into a solid. Take the profile ID from query.profiles, and name the axis as a line in the same sketch — an ordinary line, a construction line or a centerline — or as a construction axis (construct.axis), or as a straight edge of a body (query.edges); the last two must lie in the profile's own plane. The whole infinite line is the axis, not just the drawn segment, and the profile must not cross it, though touching it is how a sphere or a cone is made. The extent is two signed angles in degrees: end is required and start defaults to where the profile was drawn, and the sign is the direction, so there is no flip flag. A full turn is start 0 and end 360 and has no end caps at all. operation says what becomes of the turned solid: a body of its own, or joined to / cut from / intersected with the bodies it meets, which keep their IDs and names. thin turns only a wall along the profile's boundary rather than its whole area — a vessel, a tube, a funnel or a lampshade. surface: true turns a SURFACE instead of a solid (ADR 0301): the boundary's swept walls with no caps, answering a SHEET body — sheet: true on the reply and the tree row, and no volume to measure until feature.thicken gives it one. Its operand is profiles (one skin per boundary loop) or curves (an open or closed run of sketch curves from one sketch — a swept band, or a closed skin when the run closes), exactly one of the two; the axis and the angles read exactly as for a solid, and operation and thin are refused beside it.

feature.rib kernel

Stand a thin wall up along an OPEN run of sketch curves until it meets the part it stiffens — a rib inside a moulded housing, a web under a boss.

Detail

Stand a thin wall up along an OPEN run of sketch curves until it meets the part it stiffens — a rib inside a moulded housing, a web under a boss. Name the run with spine (sketch curves from ONE sketch, query.sketch lists them) and how thick the wall is with thickness; the material sits half either side of the curves you drew. The order you name them in does not matter — they are joined end to end by where they actually meet — and a run that branches, has a gap in it, or closes into a loop is refused. There is no depth to give: the rib grows both ways along the sketch plane's normal and stops at the first material it meets each way, and an end that meets nothing stays flat on the plane you drew on. It always joins what it meets, which keeps that body's ID, name and visibility; targets narrows which bodies it may join and which it looks at for its stopping point.

feature.rip kernel

Cut a narrow slit along the named edges of a body, so two walls that are joined along them come apart - the corners of an imported enclosure that somebody else's software modelled closed, which is what stops it developing into one flat blank.

Detail

Cut a narrow slit along the named edges of a body, so two walls that are joined along them come apart - the corners of an imported enclosure that somebody else's software modelled closed, which is what stops it developing into one flat blank. Name the edges with edges (query.edges lists one body's live edge IDs) and how wide the slit is with gap, in millimetres. gap is required and has no default: it is a cut, so a width of nothing would be a split rather than a rip, and it deliberately does NOT come from the body's sheet-metal rule because a body being ripped usually has no rule yet - that is the point. This does not require the body to be sheet metal and it does not make it so; ripping is just a cut, and a body becomes sheet metal when doc.set_sheet_metal_rule gives it one, before or after, in either order. A rip that does not part the body is not an error - a box may need three corners opened and the first two are progress - so check query.flat_pattern's pieces to see whether the part lays out as one blank yet. Only a rip that would take away all the metal is refused. Each edge must be straight.

feature.sculpt_mesh kernel

Sculpt a MESH body with one brush stroke, where it stands - grab, smooth, inflate or crease, the way a sculpting tool's brush works, as one journaled step a person and an AI make alike.

Detail

Sculpt a MESH body with one brush stroke, where it stands - grab, smooth, inflate or crease, the way a sculpting tool's brush works, as one journaled step a person and an AI make alike. The stroke is a path (points, in order) with a ball of radius rolled along it: every corner within radius of the path is moved, most at the path and smoothly less to none at the radius. inflate pushes the surface out along its normal by up to strength x radius; crease pushes it in along the path by up to the same and pinches it into a sharp groove; grab moves the surface under the path's START by its end less its start (times strength, 1 when left out), so it follows the drag; smooth pulls each corner toward its neighbours' middle, 10 x strength passes, keeping an open rim where it is. Corners in one place move together and no triangle changes, so a closed scan stays closed; a stroke deep enough to fold the surface through itself is not refused - the reply says whether the body still closes and its volume. The body keeps its ID, name, material and appearance; one undo takes the stroke back. Refused: an exact body (turn it into a mesh with body.to_mesh first), a grab with one point, a stroke that never comes within radius of the surface, and a brush that reaches fewer than four corners (remesh finer with feature.remesh_mesh first - the refusal names the edge length). If the stroke moved nothing the reply says changed false and NOTHING is recorded.

feature.set_intent

Say WHY a feature is here, in plain language - "this fillet clears the bearing", "3 mm so it prints without supports".

Detail

Say WHY a feature is here, in plain language - "this fillet clears the bearing", "3 mm so it prints without supports". The note sits beside the feature in the timeline and is an input to nothing: it changes no geometry, no rebuild and no dimension, which is what lets it be a sentence rather than a number. It is dated and attributed automatically, so a note an AI wrote can be told from one a person wrote. entities are the ids the sentence is about - the face it clears, the parameter it comes from - and they must exist when the note is written; query.features later reports each one as still alive or not, so a note whose subject was removed can be spotted instead of quietly misleading the next reader. Send intent as null to clear the note - required either way, so a forgotten field never erases something silently. Read them back on query.features. Saved with the file, and undoable in one step. Not a timeline feature itself: writing down a reason is not modelling.

feature.set_rollback kernel

Roll the model back to a point in its timeline, or forward again - the timeline's rollback marker.

Detail

Roll the model back to a point in its timeline, or forward again - the timeline's rollback marker. The part is rebuilt up to and including the feature named, and every feature after it stays in the recipe, keeps its ft: id and builds nothing until it is rolled forward: query.features lists them with rolledBack: true and says where the marker is in rollback. A feature made while rolled back is inserted at the marker. The position is saved with the document and moving it is one undoable step. Rolling forward re-runs what it brings back, and a feature that now refuses leaves the document where it was and names the feature.

feature.shell kernel

Hollow one body out to a wall of the given thickness, opening it at the named faces.

Detail

Hollow one body out to a wall of the given thickness, opening it at the named faces. The faces you name are the ones OPENED — each becomes the mouth, and what is left of it, the rim ring, keeps its face ID unless the wall is a middle one — and every other face of the body acquires the wall. The body keeps its ID, its name and its place in the tree: a shell edits the body it was given and creates nothing. One face can keep a wall of its own thickness — a box open at the top with 1 mm walls and a 3 mm floor is one wallThicknesses entry. If the body is in several separate pieces — which is what a pattern of a solid makes — the faces you name decide which pieces are shelled, and any piece you named no face of is left exactly as it was; the reply's piecesLeftSolid says how many that was, and it is 0 for an ordinary connected body.

feature.snap_fit kernel

Grow a cantilever snap-fit from a flat face: a beam length long standing square to the face, thickness thick the way it bends and width wide, with a hook at its tip that stands hook proud of the beam - a lead-in ramp at insertAngle from the beam's axis (default 30) and a retaining face at retainAngle (default 90, a permanent catch).

Detail

Grow a cantilever snap-fit from a flat face: a beam length long standing square to the face, thickness thick the way it bends and width wide, with a hook at its tip that stands hook proud of the beam - a lead-in ramp at insertAngle from the beam's axis (default 30) and a retaining face at retainAngle (default 90, a permanent catch). The beam is joined to the face's body, at the face's centre unless at says where, its hook pointing across the face's long axis unless direction says which way. With catchBodyId - the mating part, placed where it sits when snapped in - the window the hook catches in is cut through it where the hook is, clearance bigger than the hook on every side. The reply reports the beam's strain when it bends the hook's depth to go in, 1.5 x thickness x hook / length^2 (0.02 is 2%), as a number and never a verdict: compare it with the material's allowable strain - a beam that strains too much is not refused. Refused, each with details.reason, when the beam's footprint is not wholly on the face (offFace, with at), when the hook leaves no beam to bend (tooShort, with needed - the length the beam must exceed), when the window would not reach the catch body (missesCatch) and when it would cut the catch body in two (severs); and a face that is not flat, or a direction square to it, by name. One feature, one undo; both bodies keep their IDs. The reply gives the beam's root (origin, the middle of its footprint), the face's normal, the hook's direction, where the retaining face meets the beam (catchAt, from the root) and the strain.

feature.split kernel

Divide a SOLID body into separate bodies along a cutting tool, keeping every piece.

Detail

Divide a SOLID body into separate bodies along a cutting tool, keeping every piece. Name the body in body and a cutting tool as exactly ONE of plane/face/constructionPlane (an unbounded plane), tool (a sheet body - bounded), or profile (a sketch region extended perpendicular to its sketch into a fence). The largest piece by volume keeps the ID and name; the rest become new bodies in the same step. The tool is never consumed, and a tool that does not pass clean through is refused - a split that leaves one piece would change nothing. To remove solid material instead, use feature.combine with "cut"; to cut pieces off a sheet, feature.trim. A mesh body (a scan made with body.from_reference_mesh) is split by a plane only - plane, face or constructionPlane - provided it closes up into a solid (feature.repair_mesh first if not); every piece stays a mesh body, capped flat where the plane passed.

feature.split_face kernel

Divide the named faces of a SOLID body along a cutting tool, without cutting the body itself - the direct edit that draws a real, nameable boundary onto a face.

Detail

Divide the named faces of a SOLID body along a cutting tool, without cutting the body itself - the direct edit that draws a real, nameable boundary onto a face. Name faces of ONE body in faces and a cutting tool as exactly ONE of plane/face/constructionPlane (an unbounded plane), tool (a sheet body - bounded), or profile (a sketch region extended perpendicular to its sketch into a fence). Each named face is replaced by its pieces and EVERY piece is kept - there is nothing to remove here; the body keeps its ID, its name and its shape, and the new edges come back in edgeIds ready for a fillet, a draft or a press-pull on one piece alone. The tool is never consumed. A tool that crosses none of the named faces is refused - an imprint that changes nothing does not journal. To divide the BODY into separate bodies, use feature.split; to imprint a sketch onto a sheet, feature.project_curve.

feature.stitch kernel

Sew two or more SHEET bodies (ADR 0301 - surfaces with no enclosed material) into ONE body.

Detail

Sew two or more SHEET bodies (ADR 0301 - surfaces with no enclosed material) into ONE body. The FIRST body named survives with its ID and name; the rest are consumed and named in removedBodyIds. Gaps up to tolerance are closed. A result that closes into a shell with no free boundary is promoted to a SOLID automatically - the sheet flag simply disappears, exactly as feature.thicken's does - unless surface: true keeps it a sheet. A stitch that would leave separate shells is refused whole rather than consuming bodies it could not attach. Solids are refused: feature.combine is where solids join, and feature.unstitch is the inverse door.

feature.subdivide_cage kernel

Subdivide a SUBDIV (freeform) body's whole control cage once: every face is split into four-sided faces (a quad into four, an n-sided face into n) and every point moves to where the finer cage needs it, so the smooth surface stays EXACTLY the same shape and there are about four times as many cage points, edges and faces to shape with feature.move_cage, feature.extrude_cage and the rest.

Detail

Subdivide a SUBDIV (freeform) body's whole control cage once: every face is split into four-sided faces (a quad into four, an n-sided face into n) and every point moves to where the finer cage needs it, so the smooth surface stays EXACTLY the same shape and there are about four times as many cage points, edges and faces to shape with feature.move_cage, feature.extrude_cage and the rest. Every point keeps its id (cx:), and every face keeps its id for the piece at its first corner - the other pieces are new faces, listed under faces; every edge is split, so every old edge id (ce:) is RETIRED and never reused. A crease stays a crease (a soft one loses a level, which is what keeps the surface the same). One step, one undo, a timeline feature. Refused, by name: an id that is not a body, a body that is not a subdiv body, and a cage that would have more than 62500 faces.

feature.suppress kernel

Take a feature out of the part without deleting it, or put it back.

Detail

Take a feature out of the part without deleting it, or put it back. Everything made after it is re-run without it, so a fillet on a face a suppressed extrude created is refused and the document does not move. The feature keeps its ft: id and its arguments either way, and a suppression survives saving and reopening. Sets rather than toggles: send suppressed explicitly.

feature.suppressed kernel

The recipe's record of a feature that has been suppressed: it takes a place in the timeline, keeps its ft: id, and builds nothing.

Detail

The recipe's record of a feature that has been suppressed: it takes a place in the timeline, keeps its ft: id, and builds nothing. This is what feature.suppress leaves behind in the document's own operation log, and it is on the wire because reopening a document replays that log. To suppress or unsuppress a feature, send feature.suppress - not this: sent by a live client it is refused with INVALID_ARGUMENT.

feature.sweep kernel

Carry a closed sketch region along a path to make a solid — a pipe, a moulding, a rail.

Detail

Carry a closed sketch region along a path to make a solid — a pipe, a moulding, a rail. Take the profile ID from query.profiles, and name the path either as sketch curves it runs along (query.sketch) or as edges of one body (query.edges), which is how a path that leaves a plane is named. The order you name them in does not matter: they are joined end to end by where they actually meet, and a path that branches or has a gap in it is refused. The path may close on itself, which makes a ring and gives it no end caps. The profile is swept from where it was drawn and is never moved onto the path, so one end of the path has to start on the plane the profile is drawn on — that end is the start, so there is no flip flag. orientation says whether the section stays square to the path or stays parallel to the profile as drawn, twist rolls it as it travels, and guide names a second run of curves for the section to turn and follow. operation says what becomes of the swept solid: a body of its own, or joined to / cut from / intersected with the bodies it meets, which keep their IDs and names. surface: true sweeps a SURFACE instead of a solid (ADR 0301): the profile boundary's swept skin with no caps, answering a SHEET body — sheet: true on the reply and the tree row, no volume to measure until feature.thicken gives it one, and one skin per boundary loop (a hole's loop sweeps as its own tube rather than being cut). The path, guide, twist and orientation read exactly as for a solid, and operation is refused beside it.

feature.symmetry_cage kernel

Give a SUBDIV (freeform) body's control cage a SYMMETRY that its point moves keep, so one side is shaped and the other follows: a MIRROR across a plane (a bottle, a car body, a face) or a CIRCULAR symmetry of count copies round an axis (a knob, a rosette).

Detail

Give a SUBDIV (freeform) body's control cage a SYMMETRY that its point moves keep, so one side is shaped and the other follows: a MIRROR across a plane (a bottle, a car body, a face) or a CIRCULAR symmetry of count copies round an axis (a knob, a rosette). From then on feature.move_cage moves every named point's partners too - the mirror image of the move, or the move turned round the axis - and keeps a point on the plane or the axis on it. The partners are found on every move, not stored: a point lands on a partner when the symmetry sends it within a millionth of the cage's size of one, so a later extrusion on one side simply has no partners until the other side has its twin (query.cage's symmetry lists the points that have none). Every other cage edit keeps the symmetry. type none removes it. One step, one undo, a timeline feature; asking for the symmetry the cage already has records nothing. Refused, by name: a body that is not a subdiv body, a plane or axis with no direction, an argument that belongs to the other type, and a symmetry under which no point of the cage has a partner (the cage is not symmetric there).

feature.texture_mesh kernel

Press a surface texture into a MESH body, where it stands - a knurl, ribs, scales, leather grain or a picture - by moving every corner of its surface along its own normal by the pattern's height there.

Detail

Press a surface texture into a MESH body, where it stands - a knurl, ribs, scales, leather grain or a picture - by moving every corner of its surface along its own normal by the pattern's height there. size is one repeat of the pattern and depth its full height; mode raise stands the texture on the surface (material added) and mode cut sinks it in so the surface is the texture's top (material taken away, the part keeps its size). mapping box (the default) lays the pattern on any shape from the side each part of it faces; cylinder wraps it round an axis with a whole number of repeats so it closes with no seam; plane projects it along an axis. region limits it to a box. A texture needs triangles finer than itself - on average at most a quarter of size - so give edgeLength to even the surface out first in the same step (an eighth of size is a good choice); without it a coarse surface is refused, naming the length that works. Corners in one place move together, so a closed body stays closed unless the texture folds it through itself, which is not refused - the reply says whether it still closes and its volume. The body keeps its ID, name, material and appearance; one undo takes the texture back. Refused: an exact body (turn it into a mesh with body.to_mesh first), an axis missing for cylinder or plane or given for box, a canvas missing for the image pattern or given for another, a region holding none of the body, and a surface too coarse. preview: true works it all out and changes nothing. If nothing moved the reply says changed false and NOTHING is recorded.

feature.thicken kernel

Give a SHEET body - a surface with no enclosed material (ADR 0301) - a wall's worth of thickness, and it becomes a SOLID: same ID, same name, same place in the tree, the sheet flag simply gone, and volume, mass properties and the combine all reachable again.

Detail

Give a SHEET body - a surface with no enclosed material (ADR 0301) - a wall's worth of thickness, and it becomes a SOLID: same ID, same name, same place in the tree, the sheet flag simply gone, and volume, mass properties and the combine all reachable again. The sheet's own faces keep their IDs. This is the inverse door to feature.shell and feature.hollow, which start from solids; thicken starts from a sheet - a surface extrude's ribbon or tube, or an imported open shell - and a solid body is refused.

feature.thread kernel

Thread the named cylindrical faces of one body — the screw thread a bolt boss or a tapped hole carries.

Detail

Thread the named cylindrical faces of one body — the screw thread a bolt boss or a tapped hole carries. The form is ISO 68-1's 60-degree V, derived entirely from pitch, and it is cut AT the named face's own radius: THE FACE IS THE CREST, so there is no diameter argument anywhere — an external thread's major diameter is the boss's own diameter, an internal thread's minor diameter is the hole's own drilled size, and which side the thread is on is derived from the face itself (a boss threads external, a hole wall internal; there is no flip). A hole drilled at a standard's tapDrill (query.hole_standards) and threaded at the same row's pitch is that standard's internal thread with no number retyped. By default the thread is COSMETIC: the document records the feature — it appears in the timeline and will appear in drawings — and the 3D view, exports and mass properties keep the plain cylinder, which is what machined-part CAD wants and what keeps eight threaded holes from costing a mesher's bill. Send modeled true to cut the real helical grooves so STL/3MF/OBJ exports carry them — what a printed part needs — and expect a modeled thread to be the most expensive geometry in the document per feature. feature.edit flips modeled either way later.

feature.trim kernel

Cut away pieces of a SHEET body (ADR 0301 - a surface with no enclosed material).

Detail

Cut away pieces of a SHEET body (ADR 0301 - a surface with no enclosed material). Name the sheet in body, a cutting tool as exactly ONE of plane/face/constructionPlane (an unbounded plane), tool (a sheet body - bounded), or profile (a sketch region extended perpendicular to its sketch into a fence), and at least one remove point - the piece nearest each point is removed, exactly as sketch.trim's at works one dimension down. What remains stays one body where connected; a remainder in separate pieces keeps the ID and name on the largest piece by area and the rest become new bodies. The tool is never consumed. A tool that does not divide the sheet clean through is refused - a partial score removes nothing.

feature.unbend kernel

Straighten one bend of a sheet-metal part, so a slot or a hole can be cut across it and the fold put back with feature.rebend.

Detail

Straighten one bend of a sheet-metal part, so a slot or a hole can be cut across it and the fold put back with feature.rebend. Name the bend with bend - either of its cylindrical faces, innerFace or outerFace from query.bends, and it does not matter which - and the wall that STAYS PUT with face, one of that bend's own walls, also from query.bends. face is required and has no default: unbending turns one side of the fold rigidly, so which side holds still decides where the part ends up, and the two walls give two different parts. There is no angle, no direction and no radius to state: the metal already has them and this reads them off it, so the flat this puts back is exactly as long as the arc it takes away - angle in radians times (radius + kFactor x thickness). kFactor overrides the body's sheet-metal rule for this one unbend, and it is the only number here that can be overridden because it is the only one nobody can measure. Afterwards query.bends reports one fewer bend, because the metal has one fewer bend in it. A bend whose two walls are also joined somewhere else - a closed box, a corner a later feature bridged - is refused and says so, because opening it would tear metal you cannot see. Leaving a part unfolded is a perfectly good part; nothing insists you fold it back.

feature.unstitch kernel

Take a body apart into one SHEET body per face - the inverse of feature.stitch.

Detail

Take a body apart into one SHEET body per face - the inverse of feature.stitch. Works on sheet bodies and solids alike; a solid becomes its boundary faces, each a sheet body of its own. The face with the largest area keeps the body's ID and name, and the rest are new bodies named for it. Stitching the pieces back together restores the body - a closed set promotes back to a solid. A body that is already a single face is refused.

feature.untrim kernel

Remove the interior boundaries (holes) of a SHEET body's faces.

Detail

Remove the interior boundaries (holes) of a SHEET body's faces. Name the body and, optionally, which of its faces in faces - left out, every face that has an interior loop is untrimmed. Each untrimmed face keeps its ID; the holes' edges retire. A loop another face of the body fills (an imprinted seam) is not a hole and is kept. The OUTER boundary is never touched - only loops inside a face are removable, because an outer boundary's natural extension is unbounded for a flat face and this build refuses to invent a bound. A face with no interior loop, named, is refused by name; a body with none anywhere is refused whole. Solids are refused - a solid's holes belong to the features that cut them.

Solid primitives

Bodies created directly, without a sketch.

body.box kernel

Create a rectangular box body.

Detail

Create a rectangular box body. Dimensions in millimetres along X, Y and Z.

body.chain kernel

Make a print-in-place chain of ball-and-socket links along a path - a flexi chain, snake or tail that prints as one part and moves when it comes off the bed.

Detail

Make a print-in-place chain of ball-and-socket links along a path - a flexi chain, snake or tail that prints as one part and moves when it comes off the bed. The links are spaced pitch apart in a straight line along the path (each link is rigid, so it spans a chord) and each one is a hollow socket with a neck running to a ball that sits inside the next link's socket, clearance all round. Every size of a link follows from ballDiameter and clearance, and the reply states them. A joint can bend only so far before the neck meets the socket's rim (swing, in degrees, in the reply): a path that bends more than that between two links is REFUSED and says where - use a gentler curve, a shorter pitch, or a smaller clearance. Two links that are not neighbours but come close enough to print fused (a tight spiral, a path that crosses itself) are refused too, naming both. The answer is ONE body holding every link as a separate solid, so it exports as one file; the links touch nothing. The path does not have to be used up: the chain stops at the last whole link and leftover says how much path was not reached. A CLOSED path makes a ring (closed: true in the reply): the pitch is adjusted to the nearest one that divides the ring into whole links - never below minPitch - so the last ball sits in the first socket, and the reply's pitch is the adjusted one beside requestedPitch. With joint hinge each link is instead a centre knuckle with a pin through it at one end and a bored fork at the other, so the chain bends in one plane (a band or a tread): a path that leaves its plane is refused naming the first link that does. A ball chain's neck can be your own section - profile, a closed region of a sketch - in place of the round one. Set preview true to see the plan without building anything.

body.composite_curve kernel

Join sketch curves and body edges into one WIRE body: a single chain of curves with no faces and no material, which is what a sweep, a loft's centerline or a pattern follows.

Detail

Join sketch curves and body edges into one WIRE body: a single chain of curves with no faces and no material, which is what a sweep, a loft's centerline or a pattern follows. This is the only place the two kinds may be MIXED - a sweep's own path is all sketch curves of one sketch or all edges of one body, and this command's answer is one run in one identity world, so a path that starts on a drawing and carries on along a part is named here first. The curves may come from any number of sketches and any number of bodies, in any mixture, and a helix counts. THE ORDER YOU NAME THEM IN DOES NOT MATTER: they are chained by where their ends actually meet, and a run that branches, has a gap in it, or names the same curve twice is refused and says which. A single circle, ellipse, closed spline or closed edge is a whole chain on its own and makes a ring. The answer is a COPY - it does not move when the curves it was made from move, and deleting them does not delete it. A wire body has no volume, no mass and no mesh: query.edges draws it, query.measure answers its length, and the commands that need material or faces refuse it by name. The reply's edgeIds are what to name as a path.

body.cylinder kernel

Create a cylinder body, axis along +Z from its origin.

Detail

Create a cylinder body, axis along +Z from its origin.

body.derive kernel

Derive bodies from another CoCAD document - the file's own recipe is replayed and the bodies it builds arrive HERE as plain bodies in the Bodies folder, under one timeline feature, so you can cut, fillet, shell, combine or pattern them like any body: a mould from a part, a cover from a board, a fixture from an assembly.

Detail

Derive bodies from another CoCAD document - the file's own recipe is replayed and the bodies it builds arrive HERE as plain bodies in the Bodies folder, under one timeline feature, so you can cut, fillet, shell, combine or pattern them like any body: a mould from a part, a cover from a board, a fixture from an assembly. Nothing becomes a component or a placement - if the file is an assembly, its parts arrive flat, at the coordinates they stand at there, and the reply's flattened says how many placements that was. bodies names which of the source's bodies to take, by the names its tree shows; leave it out for every body, and read the reply's sourceBodies to see what it holds. at takes the source as its timeline stood just after one of its features, ft:N - the part before the later features were added - instead of as it ends. By default the geometry is EMBEDDED - this document keeps its own copy of the source and opens anywhere. Send link if you want this document to follow the source: it is then re-read from its path every time this document opens or rebuilds, query.links reports it, assembly.relink repoints it when the file moves, and doc.pack carries it; to read a linked file again NOW, without reopening, send assembly.relink with from and to both its path. Use assembly.insert_component instead when the file should stay a PART with an identity of its own - a parts-list row, joints, further placements.

body.field kernel

Create a FIELD body - a smooth, organic body defined by a list of shapes and the operations that combine them, like a short program: each node is a shape (sphere, box, capsule, cylinder, torus, halfSpace, skeleton) or an operation on EARLIER nodes named by their position in the list, counted from 0 (union, intersect, subtract - each with an optional blend that rounds the seam where the inputs meet into a smooth fillet of that radius - offset, which grows or shrinks a node's surface by a distance, and shell, which hollows a node INWARD leaving a wall of that thickness).

Detail

Create a FIELD body - a smooth, organic body defined by a list of shapes and the operations that combine them, like a short program: each node is a shape (sphere, box, capsule, cylinder, torus, halfSpace, skeleton) or an operation on EARLIER nodes named by their position in the list, counted from 0 (union, intersect, subtract - each with an optional blend that rounds the seam where the inputs meet into a smooth fillet of that radius - offset, which grows or shrinks a node's surface by a distance, and shell, which hollows a node INWARD leaving a wall of that thickness). The LAST node is the body, and every other node must be used by a later one. Example - two balls joined by a smooth neck: [{"type":"sphere","center":{"x":0,"y":0,"z":10},"radius":10}, {"type":"sphere","center":{"x":16,"y":0,"z":10},"radius":8}, {"type":"union","of":[0,1],"blend":6}]. A capsule from start to end with a different endRadius is a tapered limb; a halfSpace (point, normal facing OUT of the material) cut off by an intersect makes a flat face. A gyroid (cellSize, thickness) is an INFILL - a smooth wall of that thickness, at most a quarter of the cell, winding through all of space - so intersect it with a shape to fill that shape; an endThickness with start and end grades the wall in a straight line between them, denser where it is thicker. Example - a box with a 2 mm skin and a gyroid inside: [{"type":"box","center":{"x":0,"y":0,"z":10},"size":{"x":40,"y":40,"z":20}}, {"type":"shell","of":[0],"thickness":2}, {"type":"gyroid","cellSize":10,"thickness":1}, {"type":"intersect","of":[0,2]}, {"type":"union","of":[1,3]}]. A cubicLattice, bccLattice or octetLattice (cellSize, radius) is a STRUT lattice, an infill the same way - round struts along every cell edge, from every corner to the cell's centre, or along every face diagonal (the octet truss, the stiffest of the three for its weight) - and an endRadius with start and end grades the struts exactly as a gyroid's wall. A skeleton (points, each {x, y, z, radius}) is a smooth SKIN over a curve through its points, as thick as each point's radius and tapering smoothly between them - a limb, a horn, a handle, a branch; union several with a blend for an organic part. Example - a horn curling up from a thick base: [{"type":"skeleton","points":[{"x":0,"y":0,"z":6,"radius":6},{"x":20,"y":0,"z":12,"radius":4},{"x":34,"y":0,"z":28,"radius":2.5},{"x":38,"y":0,"z":46,"radius":1.2}]}]. The list is what is stored and query.tessellate draws the surface; feature.edit with a new list changes the body and everything made from it follows. A field body has no exact faces, so exact modelling commands refuse it: body.from_field makes a mesh body from it, for the mesh exports, the mesh booleans and printing. The reply's fieldBoundingBox is a box the surface lies inside, and smallestSize the finest size the list names. Refused, naming the node: a key that is not its type's, a missing one, an input that is not earlier, an unused node; and a list that holds no material or has no outer limit.

body.from_field kernel

Convert a FIELD body into a MESH body - triangles sampled from its surface, closed by construction, every corner on the surface.

Detail

Convert a FIELD body into a MESH body - triangles sampled from its surface, closed by construction, every corner on the surface. The field body is kept and the mesh is a new body beside it, born with its material, one undo taking it away. A mesh body is what the mesh exports (export.stl, export.3mf) write, feature.combine joins and cuts, and feature.remesh_mesh evens out; a field body has no direct exact conversion - body.from_mesh on this mesh is the way to exact faces. edgeLength sets how far apart the surface is sampled; omitted, it is an eighth of the smallest size the field names, coarsened only as far as one conversion's grid holds. The reply says the edgeLength used, how many triangles, the mesh's area and volume, and whether it closes. Refused: a body that is not a field body, an edgeLength coarser than the smallest size the field names (it could lose that feature) or finer than one conversion holds (the refusal names the finest that fits). Set preview true to see the numbers without adding anything.

body.from_mesh kernel

CoCAD Pro only.

Detail

CoCAD Pro only. Convert a MESH body with FLAT, CYLINDRICAL, CONICAL and SPHERICAL faces into an exact solid - scan-to-CAD. Triangles are merged into flat faces (a corner may sit up to tolerance off its face); a run of narrow facets whose corners all lie within tolerance of one cylinder or cone becomes ONE exact round face - a hole, a pin, a boss, a rounded corner, a slot end, a D-flat shaft, a tapered boss, a countersink, a chamfered hole or pin - provided each end is a flat face square to its axis or another round face on the same axis met at a crease, and a cone may instead run to its point (a pointed pin, a drill point); and one sphere's facets become ONE exact spherical face - a ball, a domed end on a pin (meeting it tangentially), a ball on a straight or tapered stick, the scoop on an ice-cream cone (touching it), a spherical cap on a flat, a dimple, a ball ground flat on several sides (its edge arcs meeting at corners, a domed pin ground flat on its dome, a knob on a shaft, plain or ground) - cut by any number of flat faces, or by one or two cylinders or cones on its axis and any number of flat faces that cut only the ball. Corners are placed where neighbouring faces meet, and the faces are sewn into one closed B-rep solid you can fillet, cut, dimension and export as STEP. Faces are never one per triangle. The scan is kept and the solid is a new body beside it, one undo taking it away. Refused, with the scan left a mesh, when the triangles do not close (run feature.repair_mesh first); when a part is CURVED and no cylinder, cone or sphere fits it (a blend, a torus or a freeform surface - the refusal says how many triangles); or when a round face cannot be built yet - it meets a round face on another axis other than as a tee or two crossed holes, is a cone that runs to its point beside a flat side touching it, or has an end on flat faces meeting in both a ridge and a valley (the refusal says which; a round face cut by ONE slanted flat at an end converts, and so do a moulded part's drafted rounded corner, its walls touching the cone, a tapered boss shaved flat along its length (on one side or two, its ends square, or one end a pin it chamfers - a D-flat chamfered pin, its chamfer sawn off on a slant too - or one end sawn off on a slant, wide or narrow, the wide one under a pin too, or sawn into a keel or a valley at either end, a pin on the square end too - or a flat running out up the taper - on one side, on each, beside a flat reaching both ends (a narrow end sawn on a slant or into a keel or a valley above them, or a wide end sawn on a slant or into a keel or a valley below them, too), or up to a slanted end, wide or narrow, a pin standing on the square end too, or up to an end sawn into a keel or a valley, wide or narrow, a pin on the square end too), a pointed tip ground flat on one side or sawn off on a slant or into a keel or a valley or on a bevel beside a square face (ground flat beside any of them too) or into a chisel, a square face between two slopes (a bevel or a chisel ground flat inside its square face, or a chisel ground flat across one ridge or both, too), a pin under a gable or a hip (stood on a chamfer, or with a flat ground down its side - pitched at both ends, notched across its foot, or on a slanted floor - too), a pin under a chisel - a square face between two slopes - at one end or both, a D-flat pin under a bevel or a chisel (its flat across the square face too), a pin with a V notched across its end, and a pin or a hole whose end runs down a step - or two, or across a groove or a tongue, or at both ends, or on a pin stood on a chamfer). With partial: true a curve nothing fits, and a round face that cannot be built yet, is left as a mesh instead: the exact faces become an open sheet and the rest a separate mesh body, both new, in one undoable step. An exact body is refused. Set preview true to see the result - its triangles to draw, its bounds and its counts - without adding anything; CoCAD Free previews, and adding the result to the model is part of CoCAD Pro.

body.from_reference_mesh kernel

Make a MESH BODY from a reference mesh - the step that turns an imported scan or print (an rm:) into geometry of your own, in the timeline, that can be named, hidden, painted, given a material and drawn.

Detail

Make a MESH BODY from a reference mesh - the step that turns an imported scan or print (an rm:) into geometry of your own, in the timeline, that can be named, hidden, painted, given a material and drawn. The reference mesh is COPIED, not consumed: it stays where it was, and so does the file's winding - nothing is repaired or smoothed on the way. A mesh body is triangles, not surfaces, so it is not exact geometry: fillet, combine, shell, STEP export and every other command that acts on faces and edges refuse it by name. query.tree marks it representation "mesh" with its triangle count, and query.tessellate draws it. Undo removes the body and leaves the reference mesh.

body.from_subdiv kernel

Convert a SUBDIV body into an EXACT solid - the step that lets a freeform body be filleted, combined, shelled, drawn and exported to STEP.

Detail

Convert a SUBDIV body into an EXACT solid - the step that lets a freeform body be filleted, combined, shelled, drawn and exported to STEP. An OPEN cage (a plane's, or any cage with an edge only one face meets) has no inside, so it becomes an exact SHEET instead - a surface with an edge - and the reply says sheet true, its volume and limitVolume null; feature.thicken makes a sheet a solid. The cage's smooth limit surface is fitted with one exact B-spline face per four-sided cage region (a non-quad cage face makes several), every face lying within tolerance of the surface (default 0.01 mm) and neighbouring faces meeting within angularTolerance where the surface is smooth (default 0.5 degrees); the faces are sewn into one closed solid (or one sheet). The subdiv body is kept and the solid is a new body beside it, born with its material, one undo taking it away. The reply says how close the fit came (deviation, seamAngle), how many spans each face needed, and the solid's volume beside the smooth surface's own (limitVolume). Refused, with the measured numbers: a cage the tolerances cannot be met on (loosen them), and a body that is not a subdiv body. Set preview true to see the numbers without adding anything.

body.helix kernel

Create a helix - a spring's path - as a WIRE body: one curve, no faces and no material.

Detail

Create a helix - a spring's path - as a WIRE body: one curve, no faces and no material. This is what a coil is swept along: draw a closed profile on a plane through the helix's start point, then feature.sweep with this body's edge as the path. There is no separate coil command because the sweep already is one. The height is turns times pitch and is not an argument; the answer carries it as height, and startPoint says exactly where the curve begins so a profile can be put there. Give endRadius as well as radius for a tapered helix (a conical spring, an auger, a scroll). A flat spiral is not this shape and is not built. A wire body has no volume, no mass and no mesh - query.edges is how it is drawn, query.measure answers its length, and the commands that need material or faces refuse it by name.

body.lithophane kernel

Make a canvas's picture into a lithophane BODY in the model - a thin plate that shows the picture when light shines through it, there to look at, measure, move and export before it is printed.

Detail

Make a canvas's picture into a lithophane BODY in the model - a thin plate that shows the picture when light shines through it, there to look at, measure, move and export before it is printed. It is exactly the solid export.lithophane writes with the same arguments: dark is thick and bright is thin between minThickness and maxThickness, a flat plate lies with its back on the XY plane centred on the origin, and a cylinder or a dome stands on it. The picture is read as the canvas's file holds it, before any rotation or flip the canvas has in the model. It is a MESH body (query.tree marks it representation "mesh"): move, mirror, pattern, measure and export.stl work on it, and commands that act on faces and edges refuse it by name. One undoable step in the timeline; undo removes the body and leaves the canvas. To write a file without adding anything, use export.lithophane.

body.relief kernel

Raise a canvas's picture as a RELIEF body - an opaque plaque or emboss whose surface height follows the picture, for printing in one colour.

Detail

Raise a canvas's picture as a RELIEF body - an opaque plaque or emboss whose surface height follows the picture, for printing in one colour. The picture stands on a solid back base millimetres thick and rises up to depth more; with raise light (the default) white is tallest, with raise dark black is. It sits on exactly one plane, face or construction plane - named as sketch.new names one - with its back on that plane and the relief rising along its normal (out of a face), the picture's top along the plane's y axis, centred on a face's centroid or on the plane's origin. It is a MESH body (query.tree marks it representation "mesh"), a separate body beside the part it sits on: move, mirror, pattern, measure and export.stl work on it, and exported with the part a slicer prints the two together. The picture is read as the canvas's file holds it, before any rotation or flip the canvas has in the model, and transparent areas count as white. One undoable step in the timeline; undo removes the body and leaves the canvas. For a picture that shows when light shines THROUGH it, use body.lithophane.

body.sphere kernel

Create a sphere body, centred on its origin.

Detail

Create a sphere body, centred on its origin.

body.subdiv_box kernel

Create a SUBDIV body (a freeform, smooth body) from a box-shaped control cage: a Catmull-Clark cage of width x depth x height, centred on origin, cut into widthFaces, depthFaces and heightFaces faces along X, Y and Z (2 each by default).

Detail

Create a SUBDIV body (a freeform, smooth body) from a box-shaped control cage: a Catmull-Clark cage of width x depth x height, centred on origin, cut into widthFaces, depthFaces and heightFaces faces along X, Y and Z (2 each by default). The body is the cage's smooth LIMIT surface, which lies inside the cage and rounds off every corner and edge - more faces along a side keep the surface closer to that side. The cage is what is stored; query.tessellate draws the surface. A subdiv body has no exact faces, so exact modelling commands refuse it: convert it with body.from_subdiv for an exact solid. The reply's cageBoundingBox is the cage's box, which the surface lies inside.

body.subdiv_cylinder kernel

Create a SUBDIV body (a freeform, smooth body) from a CYLINDER cage about Z: radius and height, centred on origin.

Detail

Create a SUBDIV body (a freeform, smooth body) from a CYLINDER cage about Z: radius and height, centred on origin. Each cap is cut into diameterFaces x diameterFaces faces laid onto a disc, so 4 x diameterFaces faces run round the wall, and the wall is cut into heightFaces faces along Z (2 each by default). Every face is a four-sided quad, so it shapes cleanly. The body is the cage's smooth LIMIT surface, a rounded column lying inside the cage - not an exact cylinder (use body.cylinder for that). The cage is what is stored; query.tessellate draws the surface. A subdiv body has no exact faces, so exact modelling commands refuse it: convert it with body.from_subdiv for an exact solid. The reply's cageBoundingBox is the cage's box, which the surface lies inside.

body.subdiv_from_mesh kernel

Fit a closed MESH body (a scan) with a SUBDIV body - a freeform, smooth body whose surface lies on the scan - for the organic shapes body.from_mesh cannot rebuild from flat and round faces (a figurine, a handle, a shell, a sculpted grip).

Detail

Fit a closed MESH body (a scan) with a SUBDIV body - a freeform, smooth body whose surface lies on the scan - for the organic shapes body.from_mesh cannot rebuild from flat and round faces (a figurine, a handle, a shell, a sculpted grip). The scan is laid out in even triangles paired into quads, each split into four-sided cage faces (about faces of them, 384 by default), and the cage's points are solved so its smooth limit surface sits on the scan. The reply says how close it came: deviation.max (the farthest the surface and the scan stand apart, either way) and deviation.mean, in mm - a scan is noisy and the surface is smooth, so it never follows the noise; ask for more faces for more detail. Sharp edges are rounded: a part made of flat and round faces converts exactly with body.from_mesh. The scan is kept and the freeform body is new beside it, born with the scan's material, one undo taking it away; shape its cage with the feature.*_cage tools and make it exact with body.from_subdiv, whose default 0.5-degree seams a fitted scan's cage meets (where a saddle-shaped scan's does not, its refusal names the angularTolerance that would). The reply's cageBoundingBox is the cage's box, which the surface lies inside. Refused: an exact body (turn it into a mesh with body.to_mesh first), a scan whose triangles do not close (mend it with feature.repair_mesh), and too few faces for the shape, which would fold the surface through itself (fit again with more). Set preview true to see the fit's numbers without adding anything.

body.subdiv_plane kernel

Create a SUBDIV body (a freeform, smooth body) from a flat PLANE cage: width along X by depth along Y, cut into widthFaces x depthFaces faces (2 each by default), centred on origin and facing +Z.

Detail

Create a SUBDIV body (a freeform, smooth body) from a flat PLANE cage: width along X by depth along Y, cut into widthFaces x depthFaces faces (2 each by default), centred on origin and facing +Z. The cage is OPEN - a sheet with an edge and no inside - so until its points are moved its LIMIT surface is the flat rectangle itself, edge and corners kept. The cage is what is stored; query.tessellate draws the surface. A subdiv body has no exact faces, so exact modelling commands refuse it; body.from_subdiv converts it to an exact SHEET - a surface with an edge, not a solid, since an open cage has no inside. The reply's cageBoundingBox is the cage's box.

body.subdiv_quadball kernel

Create a SUBDIV body (a freeform, smooth body) from a QUADBALL cage: a cube cut into faces x faces faces a side (2 by default) with every cage point pushed out onto a sphere of radius about origin.

Detail

Create a SUBDIV body (a freeform, smooth body) from a QUADBALL cage: a cube cut into faces x faces faces a side (2 by default) with every cage point pushed out onto a sphere of radius about origin. Every face is a four-sided quad, so it shapes cleanly, and the eight cube corners are the only points where three faces meet. The body is the cage's smooth LIMIT surface, a near-sphere lying inside the cage - not an exact sphere (use body.sphere for that). The cage is what is stored; query.tessellate draws the surface. A subdiv body has no exact faces, so exact modelling commands refuse it: convert it with body.from_subdiv for an exact solid. The reply's cageBoundingBox is the cage's box, which the surface lies inside.

body.subdiv_sphere kernel

Create a SUBDIV body (a freeform, smooth body) from a UV SPHERE cage about Z: longitudeFaces faces round Z (8 by default) and latitudeFaces from pole to pole (4 by default), every cage point on a sphere of radius about origin.

Detail

Create a SUBDIV body (a freeform, smooth body) from a UV SPHERE cage about Z: longitudeFaces faces round Z (8 by default) and latitudeFaces from pole to pole (4 by default), every cage point on a sphere of radius about origin. The bands between the rings are four-sided quads and each pole is a fan of three-sided faces - a globe's lines, for a shape pulled out along its axis; for a ball of quads only, use body.subdiv_quadball. The body is the cage's smooth LIMIT surface, a near-sphere lying inside the cage - not an exact sphere (use body.sphere for that). The cage is what is stored; query.tessellate draws the surface. A subdiv body has no exact faces, so exact modelling commands refuse it: convert it with body.from_subdiv for an exact solid. The reply's cageBoundingBox is the cage's box, which the surface lies inside.

body.subdiv_torus kernel

Create a SUBDIV body (a freeform, smooth body) from a TORUS cage about Z: ringFaces faces round the ring (8 by default) and tubeFaces round the tube (4 by default), every cage point on the torus of majorRadius (the centre to the middle of the tube) and minorRadius (the tube's own), centred on origin.

Detail

Create a SUBDIV body (a freeform, smooth body) from a TORUS cage about Z: ringFaces faces round the ring (8 by default) and tubeFaces round the tube (4 by default), every cage point on the torus of majorRadius (the centre to the middle of the tube) and minorRadius (the tube's own), centred on origin. Every face is a four-sided quad and four meet at every point, so the surface is smooth everywhere. The body is the cage's smooth LIMIT surface, a ring lying inside the cage - thinner than minorRadius, more so with fewer tubeFaces - and not an exact torus (use body.torus for that). majorRadius must be greater than minorRadius. The cage is what is stored; query.tessellate draws the surface. A subdiv body has no exact faces, so exact modelling commands refuse it: convert it with body.from_subdiv for an exact solid. The reply's cageBoundingBox is the cage's box, which the surface lies inside.

body.to_mesh kernel

Convert an EXACT body into a MESH body - triangles, at an accuracy you choose.

Detail

Convert an EXACT body into a MESH body - triangles, at an accuracy you choose. tolerance is the greatest distance a triangle may stand off the exact surface (default 0.05 mm) and angularTolerance the greatest turn a curved face makes across one triangle (default 15 degrees); at the defaults the mesh is exactly the triangles export.3mf writes for the body. The triangles are welded into one surface: a solid's mesh is closed, a sheet's is open, and the reply says which (closed). The exact body is kept and the mesh is a new body beside it, born in the same component with the same material, one undo taking it away. The reply measures the accuracy on both sides - the mesh's area and volume beside the exact body's - and says how many triangles and corners it holds. A mesh body is what feature.combine joins to a scan, feature.remesh_mesh evens out, and feature.decimate_mesh simplifies; body.from_mesh goes the other way. Set preview true to see the numbers without adding anything. Refused: a mesh body (already triangles), a curve with no face, a body whose faces the mesher could not triangulate, and more than 5000000 triangles (the refusal names a coarser tolerance).

body.torus kernel

Create a torus body, centred on its origin with its axis along +Z.

Detail

Create a torus body, centred on its origin with its axis along +Z.

User parameters

Named values on the document, written as expressions that may refer to each other. The whole set is evaluated before anything is stored, so a document never holds an expression that cannot be read.

param.create

Add a named user parameter to this document.

Detail

Add a named user parameter to this document. Its expression may refer to other parameters by name, in any order. The whole set is evaluated before anything is stored, so a document never holds an expression that cannot be read. Undoable.

param.delete

Remove a parameter.

Detail

Remove a parameter. Refused when another parameter's expression refers to it, or when a recorded operation stands on it, naming which of each - deleting it would leave an expression nobody can read. query.parameters answers both lists before you try. Undoable.

param.set

Change a parameter's expression, its kind, or its name.

Detail

Change a parameter's expression, its kind, or its name. Renaming rewrites every other expression that referred to it, so no reference is ever left dangling. The whole set is evaluated before anything is stored. Undoable.

param.set_intent

Say WHY a parameter is the value it is - "0.4 mm nozzle, so 3 mm is seven perimeters", "the bearing's outer diameter, from the datasheet".

Detail

Say WHY a parameter is the value it is - "0.4 mm nozzle, so 3 mm is seven perimeters", "the bearing's outer diameter, from the datasheet". The note sits beside the parameter and is an input to nothing: it changes no value, no expression and no rebuild, which is what lets it be a sentence rather than a number. A parameter's note is its OWN, never the note on a feature that reads it - many features read one parameter, and a reason about the value must not vanish when one of them is deleted. Dated and attributed automatically, so a note an AI wrote can be told from one a person wrote. entities are the ids the sentence is about and must exist when the note is written; query.parameters later reports each one as still alive or not. Send intent as null to clear the note - required either way. Read them back on query.parameters. A rename keeps the note. Saved with the file, and undoable in one step.

param.set_many

Change several parameters' expressions at once, in ONE undoable step - what switching to a configuration is (send the inputs query.configurations lists for it), and how to set values that only work together, such as a smaller plate and a smaller hole pitch, where setting them one at a time with param.set would be refused part-way.

Detail

Change several parameters' expressions at once, in ONE undoable step - what switching to a configuration is (send the inputs query.configurations lists for it), and how to set values that only work together, such as a smaller plate and a smaller hole pitch, where setting them one at a time with param.set would be refused part-way. The whole set is evaluated with every new expression in place, then the part is rebuilt once; if either fails nothing is changed. Names and kinds are not changed here - param.set renames. A call that changes nothing records no step.

Construction geometry

Construction planes: creating them, and repairing one whose base was edited away.

construct.axis kernel

Create a construction axis - an infinite line the model can be built against.

Detail

Create a construction axis - an infinite line the model can be built against. It is reported as a point on the line plus a unit direction and has no ends: the length a viewport draws is the viewport's own choice. query.axis reads one back, and cylinderIssue says later whether the face it was built from is still there.

construct.coordinate_system

Create a user coordinate system - a named, right-handed frame you choose, to measure and report against.

Detail

Create a user coordinate system - a named, right-handed frame you choose, to measure and report against. Unlike a construction plane, whose in-plane axes and origin are conventions CoCAD derives, every number here is yours: where the origin sits and which way +X and +Y point, with +Z always their right-handed cross product. This is what a mass-properties reference frame or an export alignment will name. It appears in the browser, can be renamed with doc.rename and hidden with doc.set_visible, and query.coordinate_system reads one back.

construct.edit kernel

Change a construction plane's distance or angle and rebuild the part from its own recipe.

Detail

Change a construction plane's distance or angle and rebuild the part from its own recipe. The sketches drawn on the plane move with it, and everything made from them is re-run, so an extrude of a sketch on an offset plane follows the new offset. Send distance for an offset plane and angle for an angle or tangent plane; what the plane is built from does not change (construct.reattach re-points that). Nothing changes unless the whole rebuild finishes: a value that breaks a later feature leaves the document exactly as it was and names what refused. One step, undone like any other.

construct.plane

Create a construction plane.

Detail

Create a construction plane. It carries a frame exactly as a sketch does, and anything that takes a plane — sketch.new today — takes it by ID. The frame is resolved once and stored; query.plane's baseIssue says later whether what it was built from is still there.

construct.point kernel

Create a construction point - one place in space the model can be built against.

Detail

Create a construction point - one place in space the model can be built against. It is reported as a position in millimetres and has nothing else: no size, no direction and no frame. query.point reads one back, and entityIssue says later whether the edge or face it was built from is still there.

construct.reattach

Re-point a construction plane at another base, or an angled plane at another edge, and recompute its frame from the same construction.

Detail

Re-point a construction plane at another base, or an angled plane at another edge, and recompute its frame from the same construction. This is the repair for a plane whose baseIssue or edgeIssue says what it was built from was split or consumed: pass one of the candidates it names. The plane keeps its ID, its name, its type and its distance or angle, so everything that refers to it goes on referring to it. Re-pointing at what the plane is already built from changes nothing and records no history step.

Queries

Read-only questions about the document, the session and the registry itself — how an AI (or any client) sees what it is doing.

query.activity

Whether anyone else is changing the document right now, what they are running, who they are, and which document (documentId) it is in.

Detail

Whether anyone else is changing the document right now, what they are running, who they are, and which document (documentId) it is in. The same fields the ai.activity_changed event carries, so a client that connected in the middle of a long command can ask once and then listen.

query.axis kernel

One construction axis: where it is, which way it runs, and what it was built from.

Detail

One construction axis: where it is, which way it runs, and what it was built from. The line is infinite - a point on it plus a unit direction - so a caller that wants to draw it picks its own length. cylinderIssue is null while the face the axis was built from still resolves, and carries a code plus any candidates when an edit split or consumed it; the axis keeps its stored line either way.

query.backups

List the kept previous versions of a document, newest first.

Detail

List the kept previous versions of a document, newest first. Every doc.save that replaces an existing file keeps the bytes it was about to destroy as a stamped sibling, the newest files.backupCount of them. Each one is a complete .cocad, so restoring a version is doc.open on the path reported here - there is no separate restore command. Answers an empty list when there are none, including when the document itself is gone.

query.bends kernel

Every bend in one body, measured off the part itself - the bend table a shop reads and the first thing a flat pattern is built from.

Detail

Every bend in one body, measured off the part itself - the bend table a shop reads and the first thing a flat pattern is built from. A bend is found as a pair of cylindrical faces sharing an axis and a swept angle: innerFace and outerFace are their fc: ids, radius is the INSIDE bend radius in millimetres and angle is how far the metal turns, in DEGREES. thickness is the stock at that bend, measured as the outer radius less the inner one rather than read from the body's sheet-metal rule - so comparing it with the rule's own thickness is how you find a part that is no longer the stock it says it is. length is how far the bend runs along its axis, and axis is a point on that axis (at the middle of the run) with a unit direction, both in document millimetres. walls lists the flat faces the bend joins, normally two; fewer means a wall has been cut away. bendAllowance is the flat metal the bend consumes - angle in radians times (radius + kFactor x thickness), the number you add between two walls when laying the part out flat - and kFactor is the body's own, from its sheet-metal rule. BOTH ARE NULL when the body carries no sheet-metal rule: where the neutral axis sits inside the metal is a property of the alloy and the tooling and cannot be measured off the finished shape, so set a rule with feature.base_flange or doc.set_sheet_metal_rule and ask again. A body with no bends answers an empty list, which is an answer and not an error - a box, an unfolded blank and a turned shaft all come back that way. Nothing is changed, nothing is recorded: this is a read.

query.board_layout kernel

Read a circuit board as GEOMETRY, for building a case around it: the board's two faces (top and bottom, by face id) and thickness, its FRAME (origin, x, y, z: z points out of the top face, and the board fills 0..width by 0..depth by 0..thickness in it, so every number below is a size), its outline's width and depth (the plan box - a notched or round board is read as its box; the top face's edges are the true outline), its through HOLES largest first (diameter, at - the centre on the top face in world coordinates, plan - the same in the frame; mounting holes are usually the largest), every PART on it (body, side top or bottom - where most of its height is, so a through-hole part with pins below is top - height above that face, its box in the frame, and its gaps to the four outline sides minX, maxX, minY, maxY, negative when it overhangs), the PORTS - one row per part and side it comes within portGap of, with the opening's centre and outward normal in world coordinates, its width along the side and height, and the same span in the frame - and the ENVELOPE, the box the board and its parts fill in the frame (a case's inside must hold it).

Detail

Read a circuit board as GEOMETRY, for building a case around it: the board's two faces (top and bottom, by face id) and thickness, its FRAME (origin, x, y, z: z points out of the top face, and the board fills 0..width by 0..depth by 0..thickness in it, so every number below is a size), its outline's width and depth (the plan box - a notched or round board is read as its box; the top face's edges are the true outline), its through HOLES largest first (diameter, at - the centre on the top face in world coordinates, plan - the same in the frame; mounting holes are usually the largest), every PART on it (body, side top or bottom - where most of its height is, so a through-hole part with pins below is top - height above that face, its box in the frame, and its gaps to the four outline sides minX, maxX, minY, maxY, negative when it overhangs), the PORTS - one row per part and side it comes within portGap of, with the opening's centre and outward normal in world coordinates, its width along the side and height, and the same span in the frame - and the ENVELOPE, the box the board and its parts fill in the frame (a case's inside must hold it). parts defaults to every other solid the same feature made: one import.step of a KiCad board brings the board and its components in together, and partsFrom says which rule chose them (given, sameFeature, none). Nothing here knows what a part IS - a port is a part near an edge. Refused: a body that is not a solid, one with no two opposite flat faces, and one thicker than it is narrow. Lengths are millimetres, Z-up. Nothing is changed, nothing is recorded: this is a read.

query.bom

The parts list - one row per component definition, with its item number, the quantity placed across the whole nested tree and the part-metadata record as the row's columns.

Detail

The parts list - one row per component definition, with its item number, the quantity placed across the whole nested tree and the part-metadata record as the row's columns. item is the row's position in the partsOnly order - 1 for the first listed definition - and it is the number a drawing's balloon prints, so a balloon and the table can never disagree; a definition that appears at two levels of the structured tree carries one item at both, because an item names the part. partsOnly, the default, is the flattened rollup a person prints: every definition once, however deep its placements sit. structured is the indented tree: rows carry children, and a child row's quantity counts inside all instances of its parent row together - a sentence that stays true even when one instance has been edited apart from its siblings. A part is a definition: a mirrored component is its own row, and so is each member definition a nested placement materializes, because a placement's content is a self-contained replay. A definition whose record carries excludeFromBom loses its row in both modes and is disclosed in excluded - the omission is never silent, and the entry names the component so one query.metadata call shows the flag. Loose bodies are not rows: the BOM of a loose-body part file is empty, and empty is an answer - the document's own record is a title block's, not a row. Never journaled - asking for a parts list is not a modelling step.

query.branches

List this document's branches, sorted by name: each one's name, the branch it was forked from (null for the original line), how many operations its recipe holds, and whether it is the one that is open.

Detail

List this document's branches, sorted by name: each one's name, the branch it was forked from (null for the original line), how many operations its recipe holds, and whether it is the one that is open. current names the open branch. A document that has never branched answers one row, main.

query.build_fit kernel

Does a body fit a 3D printer's build volume - and if not, where would it have to be cut so that every piece does?

Detail

Does a body fit a 3D printer's build volume - and if not, where would it have to be cut so that every piece does? The body stands AS MODELLED: Z is up on the printer as it is in CoCAD, so extent is the part's size along x, y and z and fits says whether that box is no larger than volume. fitsTurned says whether it would fit after a quarter turn on the bed (x and y swapped), which prints exactly the same layers - do that with feature.move and a 90 degree rotation about Z. Laying the part on its side is not tried, because that changes how it prints, and neither is setting it diagonally across the bed. When it does not fit, pieces says how many pieces along each axis (and in total) make every piece fit, and cuts lists the planes that make them: equal spacing along each axis, so no piece is a sliver. Each cut names its axis and the coordinate it sits at, and is spelled for the commands that make it: construct.plane with type offset, plane, and distance (XZ's normal points along -Y, so a y cut's distance is minus its coordinate), then feature.split with that constructionPlane - one split per cut, each piece split again by the cuts that pass through it. A cut whose distance is 0 lies ON the base plane: pass plane to feature.split directly. A mesh body (a scan) is measured off its own triangles and an exact body off its surfaces. The pieces are plain cuts - no pins, dovetails or joints yet. A plan of more than 1000 pieces is refused: that is a millimetres-versus-metres mistake, not a print. Nothing is changed, nothing is recorded: this is a read.

query.build_orientation kernel

Which way up a body should print on a filament (FDM) 3D printer.

Detail

Which way up a body should print on a filament (FDM) 3D printer. Every candidate pose - the six axis directions, plus standing on each of the body's largest flat faces - is measured and the list is answered BEST FIRST: supportVolume (mm3 of support, measured as columns straight down to the plate under every surface steeper than overhangAngle, so it over-counts where the part itself would catch them), overhangArea, contactArea (mm2 standing on the plate), height, and with loadDirection loadAcross (1 when the load pulls the layers apart, 0 when it lies along them). The ranking: least load across the layers first when a load is named, then least support, then most contact, then lowest - each measure rounded to a step (a tenth, 1% of the part's volume, 1% of its surface) so near-equal poses fall through to the next. Each pose's move is feature.move's own arguments (type rotate, axis, angle - a turn in place about the body's centre) that makes it: send it with bodies: [bodyId] to apply it; the pose as modelled (+Z up) has move null. Turning about the vertical changes none of these, so where the part sits on the bed is query.build_fit's question, and its time and filament in a pose are query.print_estimate's with that pose's up as buildDirection. A mesh body (a scan) must be closed - feature.repair_mesh mends one that is not; a sheet or a wire is refused. Nothing is changed, nothing is recorded: this is a read.

query.cage kernel

Read a SUBDIV (freeform) body's control cage - the points and faces a person shapes, which its smooth surface lies inside.

Detail

Read a SUBDIV (freeform) body's control cage - the points and faces a person shapes, which its smooth surface lies inside. points is every cage point as flat x,y,z triples in millimetres, Z-up, in the cage's own order, and pointIds names each one in the same order (cx:<body>.<n> - n is the point's place in that list and never changes; null for a point no face uses any more). faces is every cage face, each with its id (cf:<body>.<n> - n is the face's number, counted from 0, which it keeps through every cage edit; a deleted face's number is never reused, so after feature.delete_cage the numbers skip it), its corner points (indices into points, counter-clockwise seen from outside), its center and its outward unit normal. edges is every cage edge, each with its id (ce:<body>.<n> - an edge keeps its number while its two points still share a face, and an edit numbers the edges it makes after every edge that already was), its two points, the one or two faces that run it (one: the cage's open rim) and its sharpness - 0 smooth, 10 a crease at every level (an open edge is always 10), a value between sharp for that many subdivision levels before it softens. closed is false for an open cage (a plane's), which has an edge. symmetry is null, or the symmetry feature.symmetry_cage gave the cage - its type, its plane (mirror) or axis and count (circular) - with the pairs it finds NOW: pairedPoints, fixedPoints (on the plane or the axis) and unpaired, the cx: ids of points with no partner yet. The same cf: ids name the groups of query.tessellate's drawing, so a click on the surface and this list agree. An exact or mesh body is refused: it has no cage.

query.camera

Where the shared camera is for the document this connection is on: what it looks at, how far off, its bearing and height, and its projection.

Detail

Where the shared camera is for the document this connection is on: what it looks at, how far off, its bearing and height, and its projection. Session state, not document state — it is never saved and never undone.

query.canvas

One canvas, whole: its pixel dimensions, its calibration, the support and frame it lies in, and the image's own bytes as base64 - what a client draws the underlay from.

Detail

One canvas, whole: its pixel dimensions, its calibration, the support and frame it lies in, and the image's own bytes as base64 - what a client draws the underlay from. The bytes are the imported file's, undecoded; hand them to the image decoder you already have. They never change for a given canvas, so fetch them once per document and keep them. Use query.tree to list the canvases - they are the Reference folder's cv: rows.

query.canvas_circles pixels

Find the circles in a canvas's picture - holes, bosses, pins - and say where they sit on the canvas's plane and how big they are.

Detail

Find the circles in a canvas's picture - holes, bosses, pins - and say where they sit on the canvas's plane and how big they are. A first draft for a person to review, and it adds nothing to the model: draw the circles you agree with with sketch.draw on a sketch on the canvas's own support (query.canvas reports it), where each center is that sketch's own coordinate. Dark and light circles are both found, because a hole is dark lit from the front and light lit from behind. Every region that is not a circle is listed under untraced rather than guessed at, circles that share a center or a diameter are listed under concentric and equal, and every size is only as true as the canvas's calibration - which the reply repeats. Photograph the part square-on: a circle seen at an angle is an ellipse and is left untraced.

query.canvas_outline pixels

Trace the outline of the part in a canvas's picture - the largest shape the picture's edge does not cut - as a short closed chain of lines and arcs placed on the canvas's plane.

Detail

Trace the outline of the part in a canvas's picture - the largest shape the picture's edge does not cut - as a short closed chain of lines and arcs placed on the canvas's plane. A first draft for a person to review, and it adds nothing to the model: draw the elements you agree with with sketch.draw on a sketch on the canvas's own support (query.canvas reports it), where every point is that sketch's own coordinate - a line from start to end, an arc in threePoint mode through start, third and end, a circle from center and radius. The elements run in order around the outline and each begins exactly where the one before it ends. Joins that are tangent, and lines along the sketch's horizontal or vertical axis, are listed under tangent, horizontal and vertical so you can add those constraints if you agree. An outline that cannot be drawn as a short chain - a jagged, textured or very detailed edge - is left untraced, with how many pieces it would have taken, rather than handing you hundreds of segments to delete. The part's holes are traced the same way and listed under holes, largest first, each in the outline's own shape - a round hole is one circle, a slot two lines and two arcs - and draw them in the same sketch so the profile has its holes; a hole that cannot be drawn as a short chain is listed under untracedHoles instead. Every size is only as true as the canvas's calibration, which the reply repeats.

query.commands

The command registry with JSON Schemas — the self-describing API surface.

Detail

The command registry with JSON Schemas — the self-describing API surface. Pages at 50 commands — pass nextCursor back for the rest. Every row says its edition: free runs in every copy of CoCAD, and pro needs a CoCAD Pro license - CoCAD Free answers it with REQUIRES_PRO (one call of drawing.export or body.from_mesh can still be Free; the command index says which).

query.configurations

Every configuration saved with feature.configuration, compared with the parameters NOW.

Detail

Every configuration saved with feature.configuration, compared with the parameters NOW. One row per configuration in timeline order: featureId, name, suppressed, and inputs - for each parameter it names, the expression it sets, the value that expression has in the configuration, and current, the parameter's expression in the document now (null when the parameter is gone). active is true when every expression the configuration sets is exactly the parameter's current expression - the part is in that configuration; two configurations that agree on what they set can both be active. usable is false, with reason saying why, when a parameter it names is gone or its values no longer evaluate. To switch to a configuration, send param.set_many with its inputs (name and expression of each).

query.connections

Who has a socket open on this bus right now, and what each of them says it is.

Detail

Who has a socket open on this bus right now, and what each of them says it is. This is live: a client appears here when it connects and is gone when its socket closes, which is what makes it the honest answer to whether an AI actually reached CoCAD. kind is human or ai as that client declared with core.identify, or null if it never declared - there is no third value and nothing is guessed - and name is the label it chose, or null. self is the clientId of the connection asking, which is in clients like any other, so a caller can tell itself from everybody else. The order is the order they connected. This is NOT query.activity, which reports who is running a command and leaves the caller out, and it is not the identity table behind query.history, which keeps a departed client's badge for ever so that its work stays attributed. It says nothing about the open document and never fails.

query.coordinate_system

One user coordinate system: its frame - origin, xAxis, yAxis and normal (+Z) - exactly as stored, plus its name and whether it is shown.

Detail

One user coordinate system: its frame - origin, xAxis, yAxis and normal (+Z) - exactly as stored, plus its name and whether it is shown. The frame object is spelled exactly as a sketch's, so a client that draws one draws this.

query.copy kernel

Copy bodies out of this document as bytes, so they can be pasted into another one with feature.paste.

Detail

Copy bodies out of this document as bytes, so they can be pasted into another one with feature.paste. The reply IS the clipboard: CoCAD stores nothing between the two calls, so hold the content yourself and paste it whenever you like, into any document, in this core or another. The geometry is exact - it is CoCAD's own B-Rep rather than a STEP or mesh conversion - so nothing is rounded on the way through. Omit bodies to copy the whole document. bodies and names come back index-aligned with the blob, so pass names straight to feature.paste to keep what each body was called. Use export.step to write a file for another application instead.

query.curvature

Curvature sampled along every curve in a sketch, ready to draw as a curvature comb — the analysis companion to query.polyline.

Detail

Curvature sampled along every curve in a sketch, ready to draw as a curvature comb — the analysis companion to query.polyline. Each station carries the curve's own parameter u, the point x,y in sketch millimetres, the unit tangent tx,ty and the SIGNED curvature in 1/mm: positive where the curve turns left of its tangent, so a counter-clockwise circle answers +1/r and a line answers 0 everywhere. Stations are evenly spaced in the curve's parameter, not in arc length; a closed curve gets samples stations around its period with no repeat at the seam, an open one gets its two ends exactly. A station where the curve has no direction — a spline corner made of repeated poles — is omitted rather than guessed at, and the gap is visible because every station names its own u. A point curve answers no stations. Nothing here changes the sketch.

query.design_check kernel

Review one body or one sketch against the design rules this build knows, and report what each rule found.

Detail

Review one body or one sketch against the design rules this build knows, and report what each rule found. subjectId takes a body ("bd:1") for the thickness, overhang and fit rules or a sketch ("sk:1") for the sketch rules; a rule whose category cannot be about your subject is simply not applied. Every finding carries BOTH numbers - measured, what this part actually is, and threshold, what the rule asks for - because a finding you can check is worth more than a verdict you cannot. The category says how to read them: thickness in millimetres, overhang in degrees, sketch a count of degrees of freedom, fit in millimetres of diameter. A thickness finding fires where a face's thinnest wall is BELOW the rule's minimum; an overhang finding where a face leans further TOWARD the build direction than the rule allows, in query.draft's sign, so a flat top is never one and a flat underside always is - including the one resting on the build plate, because nothing here knows where you will place the part. A sketch finding fires where the sketch's dof is above what the rule accepts. A fit finding fires where a round hole or pin - a cylindrical face that closes on itself, so never a fillet or the end of a slot - is predicted to print further from its drawn diameter than the rule's maxFitError, by the line the named fit calibration fitted to its caliper readings: measured is that distance in millimetres, and a fit row alone also carries nominal, the diameter drawn, and predicted, the diameter the printer is expected to make, so you can see which way it is off. A hole is judged by the calibration's hole line and a pin by its pin line, never one line for both. A round that a feature.fit declares - what it is sized FOR - is judged against that fit's band instead of its drawn size: measured is the predicted diameter's distance from the middle of the band, threshold is half the band's width, and the row adds fitFeature (the feature.fit), target (the middle of the band) and suggested, the diameter to DRAW so this printer prints the target - which nothing applies for you. findings are ordered by severity, critical first, which is the only thing severity does: no command in CoCAD ever fails because a design rule fired, since a part that is unprintable today is the ordinary condition of a part that is not finished. buildDirection has no default - omit it and every overhang rule is listed in skipped instead of judged, because an answer computed against an axis you did not choose is wrong in a way that looks right. calibration has no default either, for the same reason: omit it and every fit rule is listed in skipped, and a calibration that recorded no holes (or no pins) skips that half and says so, while one nobody recorded is refused. skipped also names a sketch rule on a sketch nothing has solved yet. A skipped row is ruleId, reason - the sentence, in English - and reasonId, that sentence's id in CoCAD's message catalogue, so a client can show it in the person's language. unmeasured names the faces a read could not answer for - a ray that left the body, a normal the sampler could not read - so a face nobody could measure is never mistaken for a face that passed. profile and category narrow which rules are applied and both are optional; a profile or category that does not exist is refused rather than answered empty, because an empty answer reads as: your part is fine. Nothing is changed, nothing is recorded: this is a read.

query.design_rules

Every design rule this build knows - the thresholds a part is reviewed against for manufacturability, and the table you edit to make that review yours.

Detail

Every design rule this build knows - the thresholds a part is reviewed against for manufacturability, and the table you edit to make that review yours. Each rule names a category and carries exactly one threshold, which is the one its category needs: a thickness rule carries minThickness in millimetres, an overhang rule carries maxOverhang in degrees, a sketch rule carries maxDof, a count, and a fit rule carries maxFitError, millimetres of diameter. The other three are absent rather than zero, because absent means this rule is not about that and 0 is a real threshold - a fully constrained sketch. severity reads info, warning or critical, and it orders findings and nothing else: no command in CoCAD ever refuses because a design rule fired, since a part that is unprintable today is the ordinary condition of a part that is not finished. profile is the process profile a rule belongs to, and it is a row-set id rather than a record - an FDM printer with a 0.4 mm nozzle IS the rows whose profile reads fdm-0.4mm, so nothing looks it up and there is no profile file; general means a rule that is not about a process at all. This table measures nothing: the reads it is written for already exist, and are query.wall_thickness, query.draft (a printing overhang is a lean taken against the build direction, in that command's own sign), dof on query.sketch, and for fit the round holes and pins query.design_check finds, compared with the diameter a fit calibration from query.fit_calibrations predicts each one prints at. maxOverhang is read against that same sign, where 0 is a wall along the build direction and 90 a face square to it. ref names where each threshold came from, and they are rules of thumb rather than published standards: confirm them against your own machine and material. source on each row reads built-in, user, or built-in, overridden - saying whether that row is this build's own or came from your design-rules.json, which adds rules and replaces shipped ones by id, a rule at a time and whole. version names the shipped table's shape rather than your file's. It says nothing about the open document and never fails.

query.design_variants kernel

Build several versions of the part at different parameter values and weigh each one, without changing the document - "give me eight versions of this bracket".

Detail

Build several versions of the part at different parameter values and weigh each one, without changing the document - "give me eight versions of this bracket". Each variant names parameters (query.parameters lists them) with new expressions, exactly as param.set would be sent; CoCAD installs all of a variant's values at once, rebuilds the whole part from its timeline in a scratch copy, measures it and throws the copy away. Each row, in the order given: label, inputs (each with the value it evaluated to), built, and when built bodies, volume, area and mass (query.mass_properties' combined rollup - mass only when every solid has a material), size (x, y, z of every body's box together), requirements (query.requirements' counts and the ft: of each one that fails) and, when print is sent, print (seconds, grams and cost summed over every body query.print_estimate can estimate, notPrinted naming the ones it refused). A version that cannot be built is not a refusal: built is false and reason says why in the rebuild's own words, with failedFeature the ft: that refused - every other version is still built. current carries the same numbers for the document as it is now, to compare against. Rank the rows yourself by whatever matters - lightest, quickest, cheapest, still passing every requirement. To make a version the document, send its inputs as param.set, one per parameter, under one group. Nothing is changed and nothing is recorded; each version is a whole rebuild, so ask for the ones worth comparing.

query.diagnostics

The tail of this core's own log file (ADR 0028), so a client can see what the core did without being on the machine.

Detail

The tail of this core's own log file (ADR 0028), so a client can see what the core did without being on the machine. lines is the newest records OLDEST FIRST, so printing them straight down the page is the right order; matched says how many records the whole file held, so a caller can tell a complete answer from a window onto a longer one. Pass commandId to keep only the records belonging to one command - the same id the bus envelope carries and every line records, which is what lets one modelling step be followed here and in the mcp and host logs by one string; it keeps only this core process's records, because ids restart at every launch and the file is shared by every core that has run on this machine. An empty commandId filters nothing, exactly as an absent one does. level is the lowest level this process actually writes: a record quieter than it was never written, so an answer that looks empty is explained by this field and not by a missing event, and the fix is to restart the core with COCAD_LOG=debug. path and process name the file these lines came from, and path is null on a core started with COCAD_LOG=off or one whose logger could not open a file - both are a core running normally with nothing to show, so this answers rather than fails. Only the current file is read, never the rolled core.1.log and its siblings. It says nothing about the open document and never fails.

query.diff

Compare two versions of a model as features and parameters rather than as lines: which features were added, removed, moved in the timeline or changed - and which of their arguments, before and after - and which parameters changed.

Detail

Compare two versions of a model as features and parameters rather than as lines: which features were added, removed, moved in the timeline or changed - and which of their arguments, before and after - and which parameters changed. before is a .cocad file, or beforeBranch one of the open document's branches; after is another file, afterBranch another branch, or the open document when both are omitted, so leaving them out answers what has changed since that version. Each file or branch is rebuilt from its recorded steps first, so an undone step is not reported as a change, and one that does not rebuild whole is refused rather than half-compared. Steps neither list itemises - sketch drawing, undo, notes - are counted in otherSteps, and geometry compares the two fingerprints, so a difference the rows do not name is still reported. Changes nothing.

query.documents

Every document open in this core process, and which one this connection is acting on.

Detail

Every document open in this core process, and which one this connection is acting on. Each connection has its own current document, so two clients can work in different parts at the same time and neither moves the other. Answers an empty list before anything is open. Open a second document with doc.new keepCurrent, move between them with core.switch_document, and close one with doc.close. Each row says whether that document is read-only, which it is when another CoCAD holds the file it was opened from; a document that has never been saved is not read-only. Each row also gives that document's revision: a counter that moves whenever anything in the document changes, and never for a selection or a camera. Compare two readings of the same documentId to tell whether the model has moved under a plan made against an earlier one. Revisions restart at 0 in every document, so a number read from one document says nothing about another.

query.draft kernel

How each face of a body leans against a pull direction — the draft analysis that says whether a moulded or cast part can leave its tool, and which faces stop it.

Detail

How each face of a body leans against a pull direction — the draft analysis that says whether a moulded or cast part can leave its tool, and which faces stop it. One row per face, in the same order query.tree lists them, each carrying the least and greatest lean over that face in DEGREES: 0 for a wall parallel to the pull (an undrafted box side), ±90 for a face square to it (a mould floor). Positive means the face GROWS along the pull, which is the same convention feature.draft's angle and feature.extrude's taper use — so a 10 mm cube drafted +5 degrees reports +5 on its walls, the number the draft was given. (That is deliberately the opposite of the mould shop's sign, where a positive draft angle eases extraction, so read the sign against feature.draft and not against another CAD package's legend.) minAngle and maxAngle are EQUAL exactly when the face is planar. There is no threshold argument, because this read must be answerable before anybody has decided what draft the shop wants: a face has at least T degrees of draft ALONG the pull when maxAngle <= -T, and against it when minAngle >= +T. undercut is true when a face's lean spans zero — part of it belongs to each half of the tool, so no movement along that axis frees it, the inside of a sideways bore being the everyday case; a planar face is never undercut. sampled says how the two numbers were got: false means exact (a plane, in closed form), true means they are the extremes over a finite sample of a curved face and the true range may be WIDER. defined is false where the face has no normal the sampler could read — minAngle, maxAngle, undercut and sampled are then null, because nothing about that face was measured. Nothing is changed, nothing is recorded: this is a read.

query.drain_sites kernel

Suggest where a hollowed body's drain holes should go - the points to hand straight to feature.drain_hole.

Detail

Suggest where a hollowed body's drain holes should go - the points to hand straight to feature.drain_hole. Give the body and the build direction (the way its layers stack, away from the plate); the holes go where the body's sealed void is lowest along it, nearest the build plate, which is where resin pools and where it drains from. The first is at the void's lowest point; each next is as far from the others as the low part of the void allows, so one drains while another lets air in. Every point suggested is one feature.drain_hole would drill with the same diameter - through the wall, opening into the void whole. Nothing is changed. The reply's points are on the outside of the part; fit says how many were found, which can be fewer than count when the bottom of the void is small. Refused when the body has no sealed void - including one an earlier drain hole already opened, which is named - or when no hole of that diameter fits anywhere low on it. A hollowed mesh body (a scan) is read the same way.

query.drawings

Every drawing this document holds, in the order they were made, each giving its name, its drafting standard, its projection angle and its sheets in order.

Detail

Every drawing this document holds, in the order they were made, each giving its name, its drafting standard, its projection angle and its sheets in order. Each sheet gives its width and height in millimetres as drawn, its default drawing scale, the views placed on it and the BOM tables placed on it - each table a recipe saying where its header sits, which way its rows stack, which query.bom mode and which columns it prints, with the layout every column is drawn to, and never the rows, which query.bom answers; and the revision tables placed on it - each a REV block whose rows ARE stored, a person's words about the print, with the layout its five columns are drawn to; and its titleBlock, or null - the record's five stored words beside every derived cell (title, drawing number, material, latest rev, sheet n of m, scale, size, projection) with its label, value and place, worked out afresh on every read; there is no orientation field, because comparing the two lengths says which way round it is and a square sheet is neither. Each view gives the RECIPE that draws it - which bodies (an empty list meaning every solid body in the document), which direction it looks from, where on the page it sits in millimetres from the lower-left corner, its own scale or null for the sheet's, the effective scale either way, and whether hidden lines are drawn - the annotations drawn on it, each with the words it says, which corners of the model it points at (none, for a general note) and where its text sits - the GD&T symbols drawn on it, each a datum feature symbol with its letter or a feature control frame with its characteristic, tolerance, modifiers and datum references, all stored - and the dimensions drawn on it, each saying which corners of the model it measures between, which distance it states, where its text sits, the tolerance and the decimal precision it is written with (stored - a shop's allowance is nobody's measurement) and whether it prints dual units, but never the number. Neither the curves nor the measurements are here: query.view_geometry works both out afresh on every call, so a view never goes stale and a drawing can never state a length the part does not have. A build with no geometry kernel cannot place a view, and answers an empty list on every sheet. A drawing has no geometry of its own and no row in query.tree, so this is how you find out what prints a document carries.

query.edges kernel

Every edge of a body as a run of straight segments, ready to draw or to hit-test — the 3D companion to query.polyline.

Detail

Every edge of a body as a run of straight segments, ready to draw or to hit-test — the 3D companion to query.polyline. Points are flat x,y,z triples in millimetres, Z-up. The points come from the same triangulation query.tessellate returns, so an edge lies exactly on the facets it borders. A closed edge does NOT repeat its first point, so draw a loop rather than a strip when closed is true. Each edge also carries its bisector: the point halfway along it and the unit direction pointing OUT of the material there, midway between the two faces that meet at the edge — which way is "away from the part" at that corner, and the direction a fillet or chamfer handle runs along. Null where there is no such direction: an edge with one face on both sides (a cylinder's seam) or a knife edge whose two faces point exactly opposite ways.

query.explode_states

Every explode state this document holds, in the order they were made, each naming the bodies it offsets and by how much.

Detail

Every explode state this document holds, in the order they were made, each naming the bodies it offsets and by how much. A body with no row here is drawn where it lives. Each row also names the component placement its body is filed in, or null when the body is loose, so a client can group an explosion by part without a second call. The offsets are millimetres in the document's own axes, and each one is also the trail line from a part's home position to where the state draws it.

query.features

Every timeline feature this document holds, oldest first - what made each part of it, in the order it was made, with the arguments the command was given.

Detail

Every timeline feature this document holds, oldest first - what made each part of it, in the order it was made, with the arguments the command was given. A body says which feature made it through featureId on query.tree; this says what that feature was. Primitives (body.box, body.cylinder) are features too and are listed, and so are the assembly commands - a feature that made a component owns no body of its own and is listed all the same. Timeline groups come back beside them: groups lists each group with its name, and a grouped feature's row carries group naming its tg: - doc.create_timeline_group makes one. Each row also says who made it - mine, authorKind and authorName, exactly as query.history reports them for the step that minted it - so a timeline can badge the features an AI made. Each row's at is when that same step was recorded, exactly as query.history reports it (an opened document's steps carry the time it was opened), so a timeline can say when each feature was made. A feature somebody wrote a reason for also carries intent: the note, when it was written, who wrote it in the same three keys, the ids the sentence is about with each one's alive saying whether it is still in the document, and stale - true when any of them has gone, which is a note that may now mislead. feature.set_intent writes one. A document rolled back with feature.set_rollback also lists the features after its marker, each with rolledBack: true and the at its command was recorded with, and says where the marker is in rollback - after (the last feature built, null for before the first) and held (how many are not built); neither key is there when nothing is rolled back.

query.find_entities kernel

Find faces, edges or bodies by geometric predicate - the search that turns "all vertical edges of this body" or "every 3 mm fillet" into entity IDs you can hand straight to select.set, feature.fillet or feature.draft, with no pixel-picking and no ID guessing.

Detail

Find faces, edges or bodies by geometric predicate - the search that turns "all vertical edges of this body" or "every 3 mm fillet" into entity IDs you can hand straight to select.set, feature.fillet or feature.draft, with no pixel-picking and no ID guessing. Say what to look for with kind (one kind per call), where to look with bodies (absent means the whole document), and what must be true with any mix of the predicates - every predicate sent must hold at once, and a predicate about a fact an entity does not have excludes it (a plane has no radius, so a radius predicate excludes every plane; a sheet encloses no volume, so a volume predicate excludes every sheet). To OR two searches, send two calls and combine the answers. Each match comes back with the facts the search read - a face's surface, surfaceKind, area and radius; an edge's curve, length, radius and direction; a body's kind, volume, area and length - so a list can be shown with no second call, and searched says how many entities were examined, so an empty answer over a big model reads differently from an empty answer over an empty scope. Directions compare within within degrees, defaulting to exactly parallel at the kernel's own precision; radius matches within tolerance, defaulting to the kernel's linear precision. For "similar to this one": read the exemplar's facts with query.measure, then send them here as predicates. A round face's SEAM - the line where a cylinder, cone or sphere meets itself - is not one of the body's edges here: it bounds no second face, so nothing can round, chamfer or draft it, and it is neither matched nor counted in searched (query.edges still lists it). Nothing is changed, nothing is recorded, and nothing is selected - hand the IDs to select.set to select them.

query.fit_calibrations

What your printers actually make - every fit calibration this installation has recorded.

Detail

What your printers actually make - every fit calibration this installation has recorded. Each is one printer, material and nozzle, the coupon's holes and pins as designed (nominal) and as measured, and the line through each list: measured = offset + scale x nominal, in millimetres. holeFit and pinFit are separate because a machine that prints holes small prints pins large. scaleMeasured is false when every reading was one size, so the scale is 1 by assumption rather than measured; worstResidual is the furthest any reading sits from its line, so a mistyped reading shows. A fit is null for a list with no readings. Answers an empty list on a fresh installation.

query.fit_clearance

The clearance to DRAW for a joint so it prints with the gap you want, by the fit calibration of the printer it is made on.

Detail

The clearance to DRAW for a joint so it prints with the gap you want, by the fit calibration of the printer it is made on. A joint's socket is a hole and its tongue a pin, so the tongue's printed width comes from the calibration's pin line and the socket is drawn so its hole line prints it gap wider on each side: clearance is (drawnSocket - size) / 2, millimetres a side - the number to send as the clearance of feature.dovetail, feature.finger_joint, feature.snap_fit or feature.dowel. predictedTongue and predictedSocket are the widths this printer is expected to make. calibration has no default: one nobody recorded is refused, and so is one that never measured the holes or the pins this needs. clearance can come out below zero on a printer that prints holes large enough, and is answered anyway - the joint commands refuse a negative clearance and say why. Nothing is changed: this is a read.

query.fits

The ISO 286 limits-and-fits table: send a tolerance class and a nominal size and get the two deviations it means there, in millimetres, signed - H7 at 25 answers upper 0.021 and lower 0, g6 at 25 answers -0.007 and -0.020.

Detail

The ISO 286 limits-and-fits table: send a tolerance class and a nominal size and get the two deviations it means there, in millimetres, signed - H7 at 25 answers upper 0.021 and lower 0, g6 at 25 answers -0.007 and -0.020. Upper-case letters name a hole (H7, JS9, P7), lower-case a shaft (g6, k6, js7); grades run 01, 0, 1 to 18; sizes run over 0 up to 500 mm. The holes are derived from the shafts by the standard's own rule (ISO 286-1:2010 Table 2), so K, M, N are stated from grade 3 and K up to grade 8 exactly as the standard states them; j, za, zb and zc are not in the table, nor are a and b up to 1 mm, t up to 24, v up to 14 or y up to 18. it is the tolerance width IT(n) at that size, so upper minus lower. The table is a vocabulary rather than a dependency: a dimension stores the designation it was given (drawing.set_dimension's tolerance type fit) and derives its deviations from the size it measures, so nothing here is copied into a document. version names the table's shape rather than how many classes it has. It says nothing about the open document.

query.flat_pattern kernel

One body laid out flat - the blank it is cut from, and where the brake goes.

Detail

One body laid out flat - the blank it is cut from, and where the brake goes. outline is the boundary and the holes in it, as exact curves in the same vocabulary query.sketch and query.view_geometry use, in flat millimetres with the layout's minimum corner at (0, 0); width and height are how big a piece of stock it needs. bendLines is one line per bend, running down the MIDDLE of the band of flat that bend eats: allowance is how wide that band is, so the two tangent lines a shop marks are half of it either side. direction is up when the metal folds towards the side the flat is seen from and down when it folds away, and viewingFace names that side - flip both to look at the other. Nothing is unfolded and nothing is stored: this is derived from the part every time you ask, so a part and its flat pattern can never disagree and folding round-trips exactly. The part must carry a sheet-metal rule, because how much flat a bend eats depends on where the neutral axis sits inside the metal and that cannot be measured off the finished shape - set one with feature.base_flange or doc.set_sheet_metal_rule. A part with no bends is already flat and lays out as itself. unreachedWalls, unplacedBends and pieces are all normally zero, zero and one; anything else means the part does not all hang together and says which way - a wall is every piece of metal the part has, two faces the stock apart, so a tray with sharp corners and no bends counts its four sides as unreached rather than laying out as its floor alone. joinedEdges is normally empty: it names the edges along which two walls meet with NO bend between them - a corner an import modelled shut, a wall extruded square onto another - and such a part cannot be unfolded, so the layout claims the corner twice. Open them with feature.rip on exactly those edges, then ask again. Use query.bends for the bend table that goes beside this. cutLength is how far a cutter travels in millimetres: the boundary and every hole. Send any of perBend, perCutMetre and setupPerPart (and currency) and the reply also carries cost: each placed bend at the bend rate, cutLength at the per-metre rate, the setup charge once, and their total - the flat priced, with no material, margin or tax. Nothing is changed, nothing is recorded: this is a read.

query.fonts fonts

The font files on this machine, ready to name in sketch.draw's font.

Detail

The font files on this machine, ready to name in sketch.draw's font. Each entry is a path plus the family and style read out of the file itself — font takes a PATH, never a family name (ADR 0066), so this is how a client finds one. Ordered by family, then style, then path, and paged. A file that cannot be parsed is skipped rather than reported, and only the first face of a .ttc collection is listed, because that is the only face a path alone can reach. Nothing here is installed, cached on disk or modified; it is a directory scan. Set COCAD_FONT_DIRS to search somewhere else instead — directories in the reply always says where this answer came from.

query.history

The undo timeline, oldest first.

Detail

The undo timeline, oldest first. Steps flagged undone are the redo tail. Returns the most recent 50 by default. Each step says what one undo of it takes: commands (how many commands joined it under a group token), entities (everything it created or changed) and featureIds. Step numbers are minted once and never reused, so after a new command discards an undone tail the numbering skips; totalSteps counts steps, not numbers. at is when this core recorded the step, ISO 8601 UTC with milliseconds; on a document opened from a file every step is stamped as the log replays, so it is the open time rather than the authoring time.

query.hole_standards

Every fastener size this build knows, so a hole can be sized from a standard instead of from a chart.

Detail

Every fastener size this build knows, so a hole can be sized from a standard instead of from a chart. Each size carries a clearance triple - close, normal and loose, which are ISO 273's fine, medium and coarse - plus a counterbore and a countersink where the standard publishes one, and one entry per thread cut in that size carrying the drill a tap needs. Every number is a feature.hole argument value in its own unit, millimetres and degrees, so a caller picks a row and sends the number: nothing here is converted, scaled or rounded, and no command resolves a designation for you. counterbore, countersink and threads may be absent, and absent means the standard publishes no value rather than zero. standardRef beside each group names where its numbers came from, and source on each standard, size and thread reads built-in, user, or built-in, overridden - saying whether that row is this build's own or came from your hole-standards.json. kind on each standard reads fastener, insert, pilot or bearing: an insert standard's rows each carry one installDiameter, an insertLength and a minHoleDepth for a heat-set insert, and outerDiameter where the vendor publishes the knurl's; a pilot standard's rows carry the pilotDiameter a thread-forming screw wants; a bearing standard's rows carry a bought bearing's bore, outerDiameter and width - none of those three kinds carries clearance fits, heads or threads. A fastener size may also carry hardware, the parts that fit it: a socketHeadCapScrew (headDiameter, headHeight - the counterbore's own depth - socketAcrossFlats, socketDepth and the lengths that are sold), a hexNut (acrossFlats, thickness) and a washer (innerDiameter, outerDiameter, thickness), each absent where the table publishes none. It says nothing about the open document and never fails.

query.interference kernel

Which solids in this document are sharing the same space, and how much of it.

Detail

Which solids in this document are sharing the same space, and how much of it. Every pair that overlaps comes back with the volume they have in common and the box that volume sits in, so you can tell a 0.02 mm rub from a part that is half-buried in another. Bodies that merely TOUCH - two faces flush against each other, a shaft exactly the size of its bore - are not reported unless you send touching, because they share a surface and no substance; with it they come back beside the overlaps with a volume of 0 and no box. Nothing is changed, nothing is created and nothing enters the timeline: this is a question, and asking it a hundred times costs a hundred nothings. Pairs are screened on their bounding boxes before any solid arithmetic runs, so a large assembly of parts that are nowhere near each other is cheap; a document where everything overlaps everything is not. Pairs you have told this document to ignore with assembly.set_interference_ignored are left out of pairs and listed in ignored instead, so a designed press fit stops being noise without the answer ever hiding it from you. Both bodies of any pair reported here can be handed straight back to assembly.create_interference_body, which makes the material they share into a body you can measure, section or cut with - which is how you answer "how much do I have to shave off?" rather than only "they overlap".

query.joints kernel

Every joint in this document, in the order they were made - what is jointed to what, how, and on which faces.

Detail

Every joint in this document, in the order they were made - what is jointed to what, how, and on which faces. Each row names the two placements, the two faces the joint origins were inferred from, the offset, angle and flip it was created with, and values and limits - a list each, one entry per degree of freedom in the order the joint's type lists them, so a rigid joint reports two empty lists and a ball reports three numbers. The faces are reported rather than the positions they work out to, because the faces are what the document actually stores: ask query.measure about one if you want where it is now. A placement appears as child at most once, which is what makes the set a tree.

query.license_state

This copy's license state and edition (ADR 0653).

Detail

This copy's license state and edition (ADR 0653). state is unlocked (a build that checks no license - every developer build - so everything runs), licensed (a paid License File covers this release) or free (CoCAD Free: no License File, one that does not read or was refunded, or a release dated after its Download Year). unlocked and licensed are CoCAD Pro; free is CoCAD Free. reason is one word a client can switch on: no-key, licensed, no-license, unreadable, release-after-year or withdrawn. edition is personal or business when a License File decided the state, otherwise null. until is the UTC date (YYYY-MM-DD) that decides it - a Download Year covers releases dated before it - otherwise null. It never names the licensee: the core keeps no name and no email. The state is worked out again whenever a License File is added, kept or withdrawn or the UTC date rolls, with no restart, and license.changed tells every connection when it does. CoCAD Free runs everything but the CoCAD Pro features, and refuses those with REQUIRES_PRO, whose details carry {feature, command, edition, upgradeUrl, reason}. It says nothing about the open document and never fails.

Every linked component this document holds, in the order its recipe names them, and whether the file each one points at is still there.

Detail

Every linked component this document holds, in the order its recipe names them, and whether the file each one points at is still there. A linked component is one inserted with link true: the part is not embedded, so the file is re-read every time this document opens, and moving or renaming that file is what breaks it. Each row gives the path exactly as the recipe stores it, where that path points from this document today, the name the part goes by, the command that made the link, the ft: id of the timeline feature that made it (null when the recipe records no number, which a hand-written file will not), and issue - null when the file is there, or an object naming what is wrong with it. A stored path may be relative, which means beside this document's own file: resolvedPath is where it lands, and it is the same string as path for an absolute one. resolvedPath is null only when the path is relative and this document has never been saved, so there is no folder to measure it from - the issue code for that is UNRESOLVED_PATH, and the remedy is to save the document rather than to go looking for the part. The other code is INVALID_PATH, the same code the open itself refuses with, meaning there is no file where the path points. The check is about the FILE and not about the document: a link can be broken while the part is still on screen, because the file was moved after this document opened, and a broken link blocks nothing - the rest of the document goes on working exactly as it did. Embedded components are not listed and do not need to be: their bytes are in this document, so there is nothing outside it to lose. A suppressed insert is not listed either, because a suppressed record does not re-read its file. Nothing here is stored: the answer is computed where it is asked, so a file put back where it belongs reads healthy on the next call with no repair step at all.

query.mass_properties kernel

The full engineering mass-properties report: per body, the volume (mm³), surface area (mm²), centre of gravity (mm, world, the VOLUME centroid), the moments and products of inertia, the principal axes and moments, and the radii of gyration — plus a combined rollup over everything named, which is how an assembly is weighed.

Detail

The full engineering mass-properties report: per body, the volume (mm³), surface area (mm²), centre of gravity (mm, world, the VOLUME centroid), the moments and products of inertia, the principal axes and moments, and the radii of gyration — plus a combined rollup over everything named, which is how an assembly is weighed. entities is optional: absent means every body in the document; a bd: names one body and an oc: names a component placement, contributing every body it owns, nested placements included. Each body is weighed at the density it HAS: the call's density argument if one is sent (it overrides everything, which is how "weigh it all in aluminium" is asked), else the material assigned to that body with doc.set_material, else nothing — and every row says which number fed it in its own density key (g/cm³, or null). With a density, mass is answered in GRAMS and the inertia moments in g·mm²; without one those keys are NULL: assign a material or send a density, because a made-up number would be worse than a missing one. Rows may legitimately differ — a steel pin in an ABS housing — and combined then carries the true mass-weighted rollup with a null density of its own, because there is no single number to name. combined's mass is null unless EVERY solid row had a density: a sum missing one body reads as the whole assembly's mass and is not. The density-free half is answered either way: the principal AXES and the radii of gyration do not depend on a uniform density at all (a radius of gyration is sqrt(I/m), and the density cancels). frame chooses where the inertia tensor is taken: "com" (the default) is about each body's own centre of mass in world axes — the rollup's about the combined one; "world" is about the document origin in world axes; a cs: ID is about that coordinate system's origin in ITS axes. A construction plane is refused by name: its in-plane axes derive from its normal by convention, so a tensor in them would be nine numbers about axes nobody chose — construct.coordinate_system is how a chosen frame becomes something this argument takes. Principal properties are always about the centre of mass whatever frame says, because they are the frame-free half of the report. Convention: ixx is the MOMENT ∫(y²+z²)dm and ixy is the PRODUCT ∫xy·dm — positive integrals, the numbers a handbook tabulates; the inertia TENSOR's off-diagonals are their negatives. A sheet or wire body answers solid: false with every measurement null — it has no enclosed material, so it has no mass properties; measure a sheet's area or a wire's length with query.measure. A mesh body (a scan made a body with body.from_reference_mesh) is weighed off its own triangles, exactly for what they are, when they close into one consistently wound surface, and joins combined like any solid; an open or inconsistently wound one answers solid: false, as a sheet does. combined sums the solid rows only and says so: count is every row, measured is how many fed the sums. Nothing is changed, nothing is recorded: this is a read.

query.materials

Every material this build knows - a small engineering set, each row a name, a density in grams per cubic centimetre, its provenance in ref, and a default appearance as r, g and b fractions between 0 and 1.

Detail

Every material this build knows - a small engineering set, each row a name, a density in grams per cubic centimetre, its provenance in ref, and a default appearance as r, g and b fractions between 0 and 1. The library is a vocabulary rather than a dependency (ADR 0324): a document never references these rows - a caller reads one and sends the numbers themselves, so a saved model can never depend on which machine opened it or on later edits to this table. density is in the unit query.mass_properties takes; nothing here is converted, scaled or rounded. source on each row reads built-in, user, or built-in, overridden - saying whether that row is this build's own or came from your materials.json, which adds materials and changes shipped ones by name. appearance is absent on a row that names no default look, and absent never means black. version names the shipped table's shape rather than your file's. It says nothing about the open document and never fails.

query.mcp_setup

How an AI client connects to THIS install of CoCAD, worked out from what is on this machine rather than described in general.

Detail

How an AI client connects to THIS install of CoCAD, worked out from what is on this machine rather than described in general. snippet is the text to paste into an MCP client's configuration file - the whole mcpServers object, so it lands at the right nesting level - and serverKey is the name CoCAD is filed under inside it, which is what a person means when they tell an AI to use cocad. server says whether this build could find its MCP server at all: command and args are absolute paths that exist, layout is installed (beside the core) or repo (a development checkout), and env carries COCAD_CORE_PATH so a client that starts before CoCAD does can launch a core instead of refusing. When found is false, problem is one sentence saying what is missing and searched lists every path that was looked at, in order, so the answer can be checked rather than believed. clients is the clients this build knows how to set up here, each with its configPath, whether that file exists yet, and its transport: a stdio row launches CoCAD with the snippet above and its own snippet is null, while an http row connects to a running cocad-mcp --http and its snippet is that client's own spelling with <url> and <token> left where the server's address and bearer token go. The list is open and being absent from it means only that nobody has verified that client - every MCP-capable client works with the same snippet. Nothing here is guessed: a path in this reply is a path this build looked at. It says nothing about the open document and never fails.

query.measure kernel

Measure bodies, faces, edges and corners: volume, surface area, centre of gravity, arc length and radius per entity, a corner's position (its row's centroid, kind vertex, every other quantity null, nothing added to the totals), running totals over the whole list, and — when exactly two things are named — the shortest distance between them, the two points that realise it, the dX/dY/dZ between those points, and the centre-to-centre distance where both ends are round — a circular edge, a cylindrical face or a spherical face, so the spacing of two holes is measured by naming either their rims or their bores, and of two balls by naming their surfaces.

Detail

Measure bodies, faces, edges and corners: volume, surface area, centre of gravity, arc length and radius per entity, a corner's position (its row's centroid, kind vertex, every other quantity null, nothing added to the totals), running totals over the whole list, and — when exactly two things are named — the shortest distance between them, the two points that realise it, the dX/dY/dZ between those points, and the centre-to-centre distance where both ends are round — a circular edge, a cylindrical face or a spherical face, so the spacing of two holes is measured by naming either their rims or their bores, and of two balls by naming their surfaces. A spherical face's row carries its centre and radius, with axis null. The two ends may be parts of the SAME body, which is how one wall's thickness is measured: name that wall's outside face and the face directly behind it. On a hollowed (shelled) part a face inside the hollow is named for the way it POINTS - into the hollow - so the inside of the Front wall is named Back and the inside of the Back wall is named Front; pair a wall's faces by where they are, never by matching names, or the answer is the distance across the hollow. query.wall_thickness answers every face's wall at once. Lengths are millimetres, areas mm², volumes mm³, Z-up; round for display with the units.precision preference. Mass is absent here - query.mass_properties weighs a body at the material doc.set_material assigned it, or at a density you send. A SHEET body — a surface with no enclosed material (ADR 0301) — answers volume null and centroid as its surface's own: null is 'not a measurement', never zero, because a sheet has no volume to measure until feature.thicken gives it thickness and makes it a solid (ADR 0302). Every row also says where the thing CAME FROM: feature is the ft: of the timeline feature that made it, and seeds is what a face or edge was derived from in that feature's own words - a hole's wall answers ["hole:shank", ...], a box's side ["face:000000"] - so a tool can find the feature behind a face and edit it (ADR 0310). seeds is null on a body. A MESH body - one made from a scan - is measured off its own triangles, exactly for what they are: its area always, and its volume and volume centroid only when the triangles close up into one consistently wound surface; an open scan answers volume null and its surface's centroid, as a sheet does. between is null when either of two named things is a mesh body, because the distance is taken between exact surfaces. A face row names what lies under the face twice: surface is plane, cylinder or other, and surfaceKind says what an other is - plane, cylinder, cone, sphere, torus, bspline, revolution, extrusion, offset, or other for a surface with no name (ADR 0643); both are null on a body and on an edge.

query.metadata

The part-metadata record as stored - part number, description, material, revision, the exclude-from-BOM flag and any custom fields.

Detail

The part-metadata record as stored - part number, description, material, revision, the exclude-from-BOM flag and any custom fields. Name a component definition ("cp:1") to read its record, or leave entity out to read the document's own - a part file's part IS the document. Sparse: only what has been set is present, so an unset record is an empty object, and empty is an answer rather than an error. Occurrences and bodies carry no record of their own - a placement reads its definition's, and a body's part is the definition or document that owns it.

query.mirror_planes kernel

Which planes is a body a mirror image across - and, for a broken or partly missing part, how much of it still is?

Detail

Which planes is a body a mirror image across - and, for a broken or partly missing part, how much of it still is? The surface is sampled evenly by area; a plane counts a sample as matched when the sample's mirror image lands on the surface within tolerance, facing the same way. Each plane is reported with coverage, the share of the surface area matched (1 is a perfect mirror image; a part with a piece broken off one side matches less, and the planes are found from the part that survived, so the missing piece does not pull them off), deviation, the root mean square gap of the matched points, and matchedArea/unmatchedArea in square millimetres. Planes covering less than 60% are not reported, and only the best plane in any one direction is: a whole part cannot be a mirror image across two parallel planes. Best first, at most 12 (truncated says there were more - a ball or a round bar is a mirror image across every plane through its centre or axis). A plane is normal (a unit vector, its largest component positive) and offset, so that normal . point = offset on the plane; origin is a point of the plane near the middle of the matched surface. A plane square to an axis is reported exactly square to it and spelled for the commands that use it: basePlane names the base plane it is parallel to and distance is what construct.plane with type offset takes from that base plane (XZ's normal points along -Y, so a plane at y = 5 is distance -5); at distance 0 it IS the base plane, which feature.mirror takes directly. basePlane is null for any other plane. To complete a broken part from its surviving half, mirror the body across the plane and join the image to it. A mesh body (a scan) is measured off its own triangles, whichever way they are wound; an exact body off a tessellation finer than the tolerance. Nothing is changed, nothing is recorded: this is a read.

query.motion_study kernel

Drive a joint through a range of motion WITHOUT moving anything, and find out where its parts collide.

Detail

Drive a joint through a range of motion WITHOUT moving anything, and find out where its parts collide. The joint is swept from from to to in steps equal poses (both ends counted), and every pose comes back with where each moving body would stand - a rigid motion from where it is now, and its bounding box - and every pair of a moving body against a still one that would share material there, with the volume and the box, in exactly query.interference's shape. clearSteps and firstCollision are the range of motion in two numbers; the per-step list is the evidence. Nothing is changed, nothing is journaled and no event is raised: this is a question, not a drive, so the live assembly stays where it is and nobody's window moves. Leave from and to out to sweep the joint's own limits, which must both be set for that. Every pose is checked against the limits exactly as assembly.set_joint_value would check it - a study never reports a pose a drive would refuse. Bodies that move together (the joint's whole subtree) are not checked against each other, because their overlap is the same at every pose - ask query.interference about those. Pairs ignored with assembly.set_interference_ignored are skipped and listed in ignored; mesh, freeform and field bodies are passed over and listed in skipped. Send touching to count contact as a collision. Send links to move other joints WITH this one - two meshing gears, a pinion and its rack, a lead screw and its nut: each linked joint moves ratio times as far as this one, from where it stands now, its bodies join movingBodyIds, and bodies two different joints move are checked against each other at every pose.

query.mounting_features kernel

What can this part be mounted by?

Detail

What can this part be mounted by? Lists a body's HOLES, BOSSES, FLATS and the PATTERNS its holes make, so mounting a motor, a board or a bearing to something is one read: "four 3.2 mm holes on a 31 mm square round a 22 mm boss, on the front face". A hole or a boss is a cylindrical face that goes all the way round - a hole with the material outside it, a boss (a pin, a shaft, a pilot) with the material inside; a fillet or a slot's rounded end is neither, and coaxial rounds (a counterbore, a stepped shaft) are separate rows. Each has its face, diameter, direction (a unit vector, its largest component positive), start and end (the ends of its axis, in that direction) and depth or height. A hole's openings are the flat faces it opens onto, each with at - where its axis meets that face, the centre to put a matching hole or a sketch circle at - and through is true when it opens at both ends; a boss's standsOn is the flat it rises from, the same way. flats is every planar face, largest first, with its outward normal, origin (its centroid), area and the holes and bosses on it. patterns groups holes of equal diameter on parallel axes, two or more, and reports every arrangement that is true of them - line (direction, length, and spacing when equal), grid (direction, columns, rows, spacing, rowSpacing) and circle (centre, the pitch-circle diameter, and angle when equally spaced) - so four holes on a square come back as both a grid and a circle; an arrangement that does not fit is null. Not recognised: countersinks (cones), slots, threads (query.features has a hole feature's thread) and a bore split into separate faces. For the gap between two parts use query.interference (do they share material?) and query.measure on the two bodies (how far apart?). Lengths are millimetres, Z-up. Nothing is changed, nothing is recorded: this is a read.

query.named_views

Every named view this document holds, in the order they were made - each giving its camera (the five channels view.set_camera takes), its display style, the section and explode states it shows (null meaning uncut/assembled), and the entities it hides.

Detail

Every named view this document holds, in the order they were made - each giving its camera (the five channels view.set_camera takes), its display style, the section and explode states it shows (null meaning uncut/assembled), and the entities it hides. Applying one is a composition: view.set_camera with the camera, doc.set_visible for the hidden set. Nothing here says which view is showing: that belongs to whoever is looking, exactly as a camera does.

query.open_with desktop

List the programs this computer offers to open a kind of file - its own Open with list for an extension, so for 3mf or stl usually the slicers installed here (Bambu Studio, PrusaSlicer, OrcaSlicer...) and for step the CAD packages.

Detail

List the programs this computer offers to open a kind of file - its own Open with list for an extension, so for 3mf or stl usually the slicers installed here (Bambu Studio, PrusaSlicer, OrcaSlicer...) and for step the CAD packages. Each handler has an id, the name the desktop shows, and default: true on the one a double-click uses. Hand an id back as openWith on export.3mf, export.stl, export.obj, export.gltf, export.step or export.iges to write the file and open it in that program rather than the default. CoCAD keeps no list of programs of its own: this is the desktop's list, so it is empty on a machine with nothing registered for the type and on platforms where the desktop does not list handlers (canChoose: false) - open: true still opens the default there. Reading the list starts nothing.

query.parameters

Every user parameter this document holds, with its computed value, the names it refers to, the names that refer to it, and the recorded operations that stand on it - the where-used view, both halves - and the intent note, when somebody wrote down why the value is what it is (param.set_intent).

Detail

Every user parameter this document holds, with its computed value, the names it refers to, the names that refer to it, and the recorded operations that stand on it - the where-used view, both halves - and the intent note, when somebody wrote down why the value is what it is (param.set_intent). Also lists every function the expression language has.

query.pause_state

Whether the human has paused AI control, who paused it, and how much is held.

Detail

Whether the human has paused AI control, who paused it, and how much is held.

query.plane

One plane - a construction plane or one of the three base planes: where it is, and what it was built from.

Detail

One plane - a construction plane or one of the three base planes: where it is, and what it was built from. The frame is the same twelve numbers a sketch reports, so anything that can place a sketch in the model can place a plane. query.tree lists them all. baseIssue (or baseIssues, in step with base and bases) and edgeIssue are null while the references the plane was built from still resolve, and carry a code plus any candidates when an edit split or consumed one - the plane keeps its stored frame either way.

query.point kernel

One construction point: where it is, and what it was built from.

Detail

One construction point: where it is, and what it was built from. entityIssue is null while the edge or face the point was built from still resolves, and carries a code plus any candidates when an edit split or consumed it; the point keeps its stored position either way.

query.polyline

Every curve in a sketch as a run of straight segments, ready to draw — the 2D companion to query.tessellate.

Detail

Every curve in a sketch as a run of straight segments, ready to draw — the 2D companion to query.tessellate. Points are flat x,y pairs in sketch coordinates and millimetres; place them in the model with the frame query.sketch reports. A closed curve does NOT repeat its first point, so draw points as a loop rather than a strip when closed is true. Construction geometry and centrelines are included and flagged, never filtered. fullyConstrained says whether the solver pinned that curve, and dof how many degrees of freedom the sketch has left; both are null when nothing has solved it since it changed.

query.preferences

Application preferences: what they are set to now, what they ship as, and what each one accepts.

Detail

Application preferences: what they are set to now, what they ship as, and what each one accepts. Session state, not document state — a new document does not reset them.

query.print_estimate kernel

Roughly how long a body takes to print on a filament (FDM) 3D printer, and how much filament it uses.

Detail

Roughly how long a body takes to print on a filament (FDM) 3D printer, and how much filament it uses. An ESTIMATE from the body's surface and the print settings, not a slicer: the part is split into walls (walls lines of lineWidth round every layer), skins (topLayers and bottomLayers of solid layers under and over every surface facing up or down) and infill (infill percent of what is left inside), and each is timed as its volume over lineWidth x layerHeight x its average speed. Travel, retraction, layer changes and supports are NOT counted - a slicer's figure is usually somewhat longer, and its plan is the one to trust before a long print. Every setting has a default (a 0.4 mm nozzle printing PLA at 0.2 mm layers) and the reply echoes the profile it used. The part prints as modelled, +Z up, unless buildDirection says otherwise. The reply: seconds and grams (the totals), filamentLength (mm off the spool), the enclosed volume, height and layers, and walls/skins/infill each with its volume (mm3 of plastic) and seconds. A mesh body (a scan) must be closed - feature.repair_mesh mends one that is not; a sheet or a wire has no material and is refused. Give any of materialPerKg, machinePerHour and setupPerPart (and currency) and the reply also carries cost: the grams at the kilogram rate, the seconds at the hourly rate, the setup charge once, and their total - the estimate priced, with no margin or tax. Nothing is changed, nothing is recorded: this is a read.

query.printer_reachable desktop

Check that a printer answers at its address.

Detail

Check that a printer answers at its address. For OctoPrint and PrusaLink this is a GET of /api/version and for Moonraker of /server/info, each with the stored key in the X-Api-Key header; for a Bambu printer it is a secure (TLS) connection to its LAN port, 8883 unless the host names another, and nothing is sent over it. reachable says something answered; status is the HTTP status (null for Bambu); keyAccepted is true when the printer accepted the request, false when it refused it for want of a key (401 or 403) and null when that was not asked - a Bambu access code is checked when a print is sent. For a Bambu printer, certificate is the certificate it showed (sha256, serial, issuer) and certificateCheck compares it with the one trusted for it: matches, notPinned (none trusted yet - save it again), changed (a different certificate - refused until trusted with core.set_printer's certificate), inspected (issued by a program inspecting the connection, such as an antivirus) or noSerial; both are null for the other kinds and when nothing answered. address is what was dialled, and detail says the outcome in one sentence. Nothing is sent to print and nothing is changed. Waits at most timeoutSeconds for an answer (3 when omitted).

query.printer_status desktop

What a printer is doing now, asked over its own local API: OctoPrint /api/job, PrusaLink /api/v1/status (and /api/v1/job for the file's name), Moonraker's print_stats and virtual_sdcard.

Detail

What a printer is doing now, asked over its own local API: OctoPrint /api/job, PrusaLink /api/v1/status (and /api/v1/job for the file's name), Moonraker's print_stats and virtual_sdcard. state is one of idle, printing, paused, finished, attention (waiting for someone at it), error, busy, offline (OctoPrint not connected to the printer) or unknown; printerState is the printer's own word for it. job is null when nothing is loaded, else the file, progress as a percentage, secondsPrinting and secondsLeft - each null where the printer does not report it, never estimated. reachable, status, keyAccepted and address mean what they mean in query.printer_reachable, and detail says it in one sentence. A Bambu printer is asked over its encrypted LAN mode (MQTT, a full report) once a certificate is trusted for it and its access code is kept - nothing is sent to one showing a different certificate; without them this is a connection check, state is unknown and detail says what is missing. Changes nothing.

query.printers desktop

The printers this installation sends to: each with the name you gave it, its kind (the local API it speaks - octoprint, prusalink, moonraker or bambu), its host on your network, hasKey - whether an API key or access code is kept for it - and certificate: for a Bambu printer the certificate trusted for it (sha256, serial, issuer), else null.

Detail

The printers this installation sends to: each with the name you gave it, its kind (the local API it speaks - octoprint, prusalink, moonraker or bambu), its host on your network, hasKey - whether an API key or access code is kept for it - and certificate: for a Bambu printer the certificate trusted for it (sha256, serial, issuer), else null. The key itself is never shown: it is kept in Windows Credential Manager, never in a CoCAD file. canStoreKeys is false where this computer has no credential store. path is the file the list is kept in. Answers an empty list on a fresh installation.

query.profiles

The closed regions in a sketch — what feature.extrude takes.

Detail

The closed regions in a sketch — what feature.extrude takes. Every closed loop is one profile, including a loop nested inside another, and openChains names the gaps when nothing closes. A profile ID names a region, not a position in this list: it survives edits elsewhere in the sketch, and the list order is not the ID order. Curves that cross without sharing an endpoint are NOT split at the crossing.

query.provenance kernel

What made one face, edge or vertex, and what stands on it - the document's own record of where a piece of geometry came from and what would break if it went away.

Detail

What made one face, edge or vertex, and what stands on it - the document's own record of where a piece of geometry came from and what would break if it went away. madeBy is the ft: of the timeline feature that CREATED this element's durable name, and seeds are what that feature built it from (a sketch curve cu:, a hole role like "hole:shank", a primitive's canonical face) - an element a later feature merely carried through keeps its name, so madeBy is its origin and not the last thing that touched it. dependents lists every committed operation whose arguments name this element: its command, the ft: it minted if it minted one, that feature's label, and via - the id the arguments spelled. They are matched by DERIVATION, not by the id string, so a reference is still found after a rebuild renumbered it. alive says whether this element is still in the body; when it is not, successors names what replaced it, so a stale reference can be followed by hand. Every answer comes from the operation log and the naming tables - nothing is guessed from geometry, and a question the records cannot answer comes back null rather than invented. A body is not an element and is refused: query.tree's featureId says which feature made one. Nothing is changed, nothing is recorded: this is a read.

query.recent

List the documents most recently saved or opened, newest first.

Detail

List the documents most recently saved or opened, newest first. A document joins the list whenever doc.save or doc.open names it, and the newest files.recentCount of them are kept (10 by default, 0 to remember none). Each entry says whether the file is still there, so one that has been moved or deleted is reported rather than quietly dropped - open it with doc.open on the path reported here. Answers an empty list on a fresh installation, and when remembering is switched off.

query.recipe

Read a recipe file back - its name and the ordered list of commands inside it - so you can run them yourself, one at a time or all at once.

Detail

Read a recipe file back - its name and the ordered list of commands inside it - so you can run them yourself, one at a time or all at once. Every step is checked against THIS build's registry first, so a recipe you can read is a recipe you could run: a command this build does not have, arguments its schema refuses, a step that only reads or one that acts on the running core is refused whole, naming the step by index. Nothing is run and nothing is changed - the steps come back to you to send. inputs lists the parameters a recipe filed from a whole document builds; pass inputs to build it at other values, and one param.set per input you give is appended to the steps. Needs no open document.

query.recognize_features kernel

What features was this body made with?

Detail

What features was this body made with? Reads a body - typically one import.step brought in with no recipe - back as the HOLES, COUNTERBORES, COUNTERSINKS, SLOTS, FILLETS and CHAMFERS a person would have modelled, and lists every face no rule explains, so an empty finding never means "all recognised". holes: each plain round bore (query.mounting_features' own hole rows, the same arithmetic) with its face, diameter, direction, start, end, depth, through (open at both ends), openings (the flat faces it opens onto, with at - its centre on that face) and bottom - for a blind hole, the face closing it and its kind, flat or cone (a drill point), or null when nothing closes it squarely. counterbores: a bore whose mouth is a wider coaxial bore closed by a flat step, as ONE row spelled the way feature.hole takes it - head "counterbore", diameter (the shank's), headDiameter, headDepth (the step, from the entry plane), depth (where the shank's bore ends, from the same plane) - with face (the head's bore), shank, step, direction (into the material), entry (the mouth's centre on the entry plane), through, openings and bottom. countersinks: a bore whose mouth is a whole-turn cone on its axis - head "countersink", diameter, headDiameter (the rim), headAngle (the cone's included angle, degrees), sinkDepth (the cone's own depth, the number feature.hole derives), depth, face (the cone), shank, direction, entry, through, openings and bottom. slots: two concave half-cylinders of one radius on parallel axes, each running smoothly into the same two parallel flat walls - ends and walls (their faces), width (the diameter), length (tip to tip), depth, centres (the two end arcs' centres on the entry plane, the points sketch.draw type "slot" takes), direction (into the material), through and bottom (the flat floor, or null). fillets: each partial cylinder or torus running smoothly into two or more other faces, with its face, surface (cylinder or torus), radius (a torus's tube radius), turn (its arc in degrees - 90 for a quarter round), concave (true for a fillet in an inside corner, false for a round over an outside edge, null on a sheet) and blends (the faces it runs into). chamfers: each flat strip creased to two flat faces along parallel straight edges of equal length, with its face, between (the two faces, each with the distance from the virtual edge where their planes would have met - the numbers feature.chamfer takes), angle (between those two faces' normals), length and width. unexplained: every other face with its surface word (plane, cylinder, cone, sphere, torus, bspline, ...), the body's own outer flats included - the stock those features were cut from is not a feature this read names. faces is the body's face count. Known limits, said rather than guessed: a counterbore whose head does not open onto a flat face (a chamfered or filleted mouth) is two hole rows and a chamfer or fillet row; a countersink on a counterbore is a countersink and a hole; a slot with a rounded floor, an arc slot or a slot whose end arcs are split into several faces is not a slot and its ends read as 180-degree fillets; a bore split into separate faces by a slot is not a hole; a variable-radius blend, a corner patch where fillets meet and a sphere are unexplained. Lengths are millimetres, angles degrees, Z-up. Nothing is changed, nothing is recorded: this is a read.

query.recovery

List the unsaved sessions this installation can still recover, newest first.

Detail

List the unsaved sessions this installation can still recover, newest first. CoCAD records every command that changes a document as it commits, and deletes that recording when it shuts down cleanly - so anything reported here is work from a session that crashed. Recover one with doc.recover on the path reported here. Answers an empty list when there is nothing to recover, which is the ordinary case.

query.reference_mesh kernel

The triangles of one reference mesh, in millimetres, Z-up - what a viewport draws an imported scan or print as.

Detail

The triangles of one reference mesh, in millimetres, Z-up - what a viewport draws an imported scan or print as. positions is flat x,y,z triples and indices is three entries per triangle, pointing into them. There are NO normals, and that is a fact about the file rather than an omission: an imported mesh keeps the winding the file gave it, because a real STL often disagrees with itself about which way a facet faces, so draw a reference double-sided and shade it flat from each triangle. The answer never changes for a given mesh - nothing in CoCAD edits one - so read it once per document and keep it. Use query.tree to list the reference meshes and query.tessellate for a body.

query.render_providers

Who can currently draw a screenshot.

Detail

Who can currently draw a screenshot. Empty means view.screenshot will fail with NO_RENDER_PROVIDER.

query.requirement_blame kernel

Which feature broke a requirement - the change after which it stopped being met.

Detail

Which feature broke a requirement - the change after which it stopped being met. Give featureId, a requirement's ft: from query.requirements. CoCAD rebuilds the model as it stood before each recorded change, newest first, and measures the requirement there with the same read query.requirements uses, until it finds the latest point where the requirement WAS met (or where what it measures did not exist yet). brokenBy names the feature (ft:) the change right after that point made, brokenByCommand the command, and before and after say what the requirement measured on either side of it - so "the fillet at ft:7 took the wall from 1.8 mm to 1.2 mm" is read straight off the reply. A change that made no feature of its own (a doc.delete, a doc.set_material) has brokenByCommand and a null brokenBy. Nothing is found when the requirement is met now, is suppressed, was never met at any earlier point, or the search stopped - reason says which, in English, with reasonId (and reasonArgs when it takes any) naming that sentence in CoCAD's message catalogue so a client can show it in the person's language; at most 40 earlier models are rebuilt, and searched counts them. Like git blame, it answers about the timeline as it is now: an edit to an early feature is blamed on that feature's place in the timeline. Nothing is changed. Each model searched is one rebuild, so ask it about a requirement that is failing, not on every change.

query.requirements kernel

Every requirement stated with feature.require, checked NOW against the current model - the test results for the part.

Detail

Every requirement stated with feature.require, checked NOW against the current model - the test results for the part. One row per requirement in timeline order: its statement, the check (quantity, entities, axis, atLeast, atMost, unit), status (pass, fail, unmeasured or suppressed), measured (the number, or null), reason (why it could not be measured, in English, with reasonId and reasonArgs naming that sentence in CoCAD's message catalogue when it has one), face (for wallThickness, the fc: where the wall is thinnest) and read - the exact command and arguments that produced the number, so you can ask it again and see the whole answer. unmeasured is never a pass: a requirement whose body was deleted or whose read now refuses is reported with the read's own sentence. counts sums the rows. Read this after every change you make, before saying the part is done: a fail means the change broke something the person asked for. Nothing is stored and nothing is changed: every read is a fresh check, so it is never stale.

query.rigid_groups kernel

Every rigid group in this document, in the order they were made, each naming the placements it welds.

Detail

Every rigid group in this document, in the order they were made, each naming the placements it welds. A group has no geometry of its own, so this is the only way to find out what is welded to what - and the members are read off the placements rather than stored on the group, so a row here can never disagree with the tree.

query.rotation_axes kernel

Which axes does a body repeat itself about, and how many times - and, for a broken or partly missing part, how much of it still does?

Detail

Which axes does a body repeat itself about, and how many times - and, for a broken or partly missing part, how much of it still does? A flange with six lugs repeats six times about its centre; a sprocket with a tooth gone still repeats twenty times, minus the tooth. The surface is sampled evenly by area; for a count n, each of the turns k * 360 / n is tried, and coverage is the share of the surface area whose turned image lands on the surface within tolerance, facing the same way, averaged over every turn of the pattern (1 is a perfect repeat; a part with a piece broken off matches less, and the axis is found from the part that survived, so the missing piece does not pull it off). count is the LARGEST count that matches as well as the best (a part that repeats six times also repeats three times and twice), at most 100. An axis about which the part matches under ANY turn - a revolved part, a cylinder, a ball - is round: true, with count and angle null. deviation is the root mean square gap of the matched points, and matchedArea / unmatchedArea are in square millimetres. Axes covering less than 60% are not reported, and only the best axis in any one direction is; best first. Each axis is spelled for feature.pattern's circular type: direction (a unit vector, its largest component positive) and origin (the point of the axis nearest the middle of the surface) are its axis, count its count and angle its angle. To complete a broken part from what survives, pattern the body about the axis with that count and angle, operation join and targets the body itself - every copy fills in what another lost. An exact body's axis is placed exactly on a whole round face of it (a bore, a hub, a pin) when it lies along one, so the copies meet the original exactly. A mesh body (a scan) is measured off its own triangles, whichever way they are wound; an exact body off a tessellation finer than the tolerance. Nothing is changed, nothing is recorded: this is a read.

query.section_states

Every section state this document holds, in the order they were made, each giving its cutting plane as a point on the plane and a unit normal - millimetres in the document's own axes, the normal pointing at the material the cut removes.

Detail

Every section state this document holds, in the order they were made, each giving its cutting plane as a point on the plane and a unit normal - millimetres in the document's own axes, the normal pointing at the material the cut removes. Nothing here says which state is showing: that belongs to whoever is looking, exactly as a camera does.

query.selection

The shared selection: which entities the human and any connected AI are pointing at, in order, in the document this connection is on.

Detail

The shared selection: which entities the human and any connected AI are pointing at, in order, in the document this connection is on. Session state, not document state — it is never saved and never undone.

Find parts shaped like one body: every other body in the open document and in the .cocad files paths names (a folder is searched whole, every .cocad under it) is ranked by how close its SHAPE is to body's, closest first.

Detail

Find parts shaped like one body: every other body in the open document and in the .cocad files paths names (a folder is searched whole, every .cocad under it) is ranked by how close its SHAPE is to body's, closest first. Shape is compared by the D2 shape distribution - the distances between a thousand points scattered evenly over each surface - so where a part sits and how it is turned change nothing, and SIZE is divided out: a 10 mm cube and a 30 mm cube are the same shape. It tells proportions apart well and fine detail weakly - two blocks of one size with different holes read as close. Each match carries distance (0 is the same shape, a cube and a ball are about 0.016 apart, a cube and a 10:1 bar about 0.27; never more than 3), size (the body's mean point-to-point distance, mm) and sizeRatio (its size over body's, so 3 is three times as big), with path null for a body in the open document. Each file is rebuilt from its recorded steps, as doc.open would, without opening it - once: what a rebuild found is kept in a per-user shape index, so a later search answers a file whose size and write time have not changed without rebuilding it again (filesFromIndex counts those; the answer is the same either way). A file that does not read or rebuild is listed in skipped with why (message, in English, with messageId and messageArgs naming that sentence in CoCAD's message catalogue when it has one), and the search goes on. A body with no surface to compare - a curve, or a subdiv or field body not yet converted - is listed in notCompared. compared counts the bodies ranked. More than 1000 files under paths is refused: name a narrower folder. No document is changed and nothing is recorded: this is a read.

query.sheet_metal_rules

Every sheet-metal rule this build knows - a thickness, the inside bend radius to fold it at, the K-factor that says where the neutral axis sits across that thickness, and the bend relief to cut where a bend meets an edge.

Detail

Every sheet-metal rule this build knows - a thickness, the inside bend radius to fold it at, the K-factor that says where the neutral axis sits across that thickness, and the bend relief to cut where a bend meets an edge. Lengths are millimetres; kFactor is a fraction strictly between 0 and 1, where 0 is the inside face and 1 the outside. relief.type reads rectangular, round or tear, and a tear carries no width and no depth because it is a rip rather than a cut-out - absent there never means zero. material names the stuff the rule was written for, spelled as query.materials spells it, but it is a word on the row rather than a reference: nothing looks it up, and a rule carries every number a bend needs without one. The table is a vocabulary rather than a dependency (ADR 0427): a feature stores the numbers, never a reference to a row here, so a saved model's flat pattern can never change because a machine's rule table did - and a thickness this table does not list is folded by sending the numbers yourself. ref names where each rule's numbers came from, and they are typical air-bend values rather than a published standard: confirm them against your own press brake. source on each row reads built-in, user, or built-in, overridden - saying whether that row is this build's own or came from your sheet-metal-rules.json, which adds rules and changes shipped ones by id. version names the shipped table's shape rather than your file's. It says nothing about the open document and never fails.

query.sheet_sizes

Every drawing-sheet size this build knows - the ISO A series and the ANSI sizes - so a sheet can be set from a standard instead of from a chart.

Detail

Every drawing-sheet size this build knows - the ISO A series and the ANSI sizes - so a sheet can be set from a standard instead of from a chart. Each row gives its two EDGES in millimetres rather than a width and a height: shortEdge and longEdge, because which way round a sheet is drawn is the sheet's own field and not the size's. series reads iso-a or ansi, and ref names where the numbers came from - the ANSI rows are exact conversions of their inch definitions, so nothing here is rounded. The table is a vocabulary rather than a dependency (ADR 0333): a sheet stores the two lengths, never a reference to a row here, so a saved drawing's page size can never change because a machine's table did - and a size this table does not list is set by sending the two lengths yourself. version names the table's shape rather than how many rows it has. It says nothing about the open document and never fails.

query.shortcuts

Every keyboard shortcut CoCAD answers, so a shortcut editor - or a person asking what a key does - needs no second list.

Detail

Every keyboard shortcut CoCAD answers, so a shortcut editor - or a person asking what a key does - needs no second list. Each row gives an id, the label a person reads, the scope it is answered in, and the binding it ships with. scope reads global (answered wherever the focus is), model (the viewport with no sketch open) or sketch (the viewport with a sketch open): that is why F fits the view outside a sketch and arms the Fillet tool inside one, and it is what decides whether two bindings collide - global overlaps both of the others and model and sketch never meet. A binding is written unspaced with the modifiers Ctrl, Alt and Shift first, in that order, then the key. Esc is not in this list and cannot be bound to anything: it is the way back out of whatever is happening. The mouse is not here either - which product's mouse the viewport follows is the navigation.scheme preference. version names the shape of a row rather than how many rows there are. It says nothing about the open document and never fails.

query.sketch

Everything in one sketch: what it is drawn on, where that is in the model, its curves and its constraints.

Detail

Everything in one sketch: what it is drawn on, where that is in the model, its curves and its constraints. Curves and constraints page independently. dof is the degrees of freedom left at the last solve, and fullyConstrained on each curve says whether the solver pinned it; both are null when nothing has solved this sketch since it last changed. conflicting names the constraints that last solve could not satisfy together, whoever asked for it - [] when it settled, and null when nothing has solved this sketch since it last changed. On a face sketch, supportIssue is null while the stored face reference still resolves, or names what became of the face when it does not. A driving dimension that was given its number as an argument expression carries that text as expression - the parameter arithmetic the value is re-computed from on every rebuild - and a dimension whose number was typed carries none.

query.strength kernel

Will this part hold?

Detail

Will this part hold? A first-order strength check of one solid under one load case: the faces named in fixed are held still, each load pushes its face with a total force in newtons, and the reply answers how far the part bends and how close it comes to giving way. displacement: max (mm, the largest movement anywhere), at and direction. stress: max (MPa, the largest von Mises stress), at and face (the face nearest it). safetyFactor: yieldStrength over that stress - under 1 means it yields, 2 or more is the usual margin - or null when nothing is stressed; with buildDirection it is the smaller of that and acrossLayers.safetyFactor. acrossLayers (only with buildDirection): max (MPa, the largest stress pulling two printed layers apart), at and safetyFactor (layerStrength over it). hotFaces: up to ten faces with the highest stress next to them, highest first - where to add material. material and buildDirection echo what was used. cellSize, cells and modelledVolume say how finely the part was sampled (equal cubes; detail smaller than one cube is not seen), and converged and iterations say whether the solve finished. notModelled names what this check leaves out, so a reply is never read as more than it is: contact between parts, large deflections, buckling, fatigue and creep, stress concentrations finer than one cube, and a hold that reaches about one cube deep. Refused: a sheet or wire body, a face of another body, a face that touches no cube (send a smaller cellSize), material not joined to a held face, a load whose every cube is held, and more than 400,000 cubes. Lengths millimetres, forces newtons, stresses megapascals, Z-up. Nothing is changed, nothing is recorded: this is a read.

query.tangent_chain kernel

The smooth run of edges one edge belongs to: every edge reachable from it by stepping across a vertex where the curve carries straight on.

Detail

The smooth run of edges one edge belongs to: every edge reachable from it by stepping across a vertex where the curve carries straight on. This is how you round a whole rounded boundary in one feature.fillet instead of naming its arcs and straights one at a time — a rounded pocket is four lines and four arcs, and they are one chain. The answer always includes the edge you named, so a chain of one means nothing continues it. Reads the exact geometry, so it never moves with display density.

query.templates

List the templates a new document can be started from, in name order, and say where CoCAD keeps them.

Detail

List the templates a new document can be started from, in name order, and say where CoCAD keeps them. A template is an ordinary .cocad file in that folder: start from one with doc.open on its path followed by doc.save to wherever the new part belongs, and make one with doc.save into the directory reported here - there is no template format and no template-only command. The folder is reported even when it does not exist yet, because saving into it is what creates it. A template's name is its file name, so renaming the file renames the template. Answers an empty list on a fresh installation.

query.tessellate kernel

Triangle mesh for a body, in millimetres, Z-up.

Detail

Triangle mesh for a body, in millimetres, Z-up. Deterministic for equal inputs.

query.thumbnails

Read the preview pictures CoCAD has cached for these documents, in the order asked for.

Detail

Read the preview pictures CoCAD has cached for these documents, in the order asked for. Each entry answers the PNG as base64 or null when nothing is cached for that path - a document CoCAD has never had a picture of, and one whose picture has fallen off the end of the list, are the same answer. A preview is kept even when the file itself has gone, because a picture of what used to be there is the clearest way to say where it was.

query.tolerance_stack

A 1D tolerance stack-up: add a chain of sizes, each with its tolerance and a direction, and get the result's worst case and its statistical (RSS) spread.

Detail

A 1D tolerance stack-up: add a chain of sizes, each with its tolerance and a direction, and get the result's worst case and its statistical (RSS) spread. Each contributor is a drawing dimension (dimensionId - its measured size and its own tolerance, a fit's deviations derived at that size) or a size in hand (nominal, with a tolerance in query.drawings' spelling, a fit looked up in ISO 286 at the nominal); sign 1 adds it and -1 takes it away, so a gap is the housing's length minus each part inside it. worstCase puts every size at the end of its band that pushes the result furthest; rss reads each band as a symmetric 3-sigma spread about its middle and combines them in quadrature, carrying the shift of an asymmetric band. Both give max and min, and upper and lower as deviations from the stack's nominal. Each contributor's worstShare and rssShare say how much of the variation it is - the one to tighten first has the largest rssShare. With a requirement ({min, max}) the reply says whether each method stays inside it. Nothing is changed: this is a read, and it needs no open document unless a dimensionId does.

query.tree

The scene tree.

Detail

The scene tree. Summary by default (depth 2) so large models stay cheap to read; ask for more depth explicitly. Pages at 200 nodes — pass nextCursor back for the rest.

query.version

Which build of this core is running.

Detail

Which build of this core is running. id is the build's ONE name - <version>+<commits>.g<sha8>, plus .dirty.<hash> when it was built from uncommitted changes - and it is the string the installer's VERSION.txt carries, the window shows, and every saved file's generator records, so quote id in a bug report and nothing else needs quoting. commits counts the commits behind it and only ever grows, so a build 'at or after' another is a number compare. Beside it: version, commit, dirty, builtAt (the date), build (the preset that produced it), and one capabilities entry per optional library saying whether that library is linked. The command surface depends on the build - a core with no geometry kernel never registers body.box at all. The capability list is open: read the entries that come back rather than naming keys, because a build gate added later appears here without a client change. It says nothing about the open document and never fails.

query.vertices kernel

Every corner point of a body — the exact points, not mesh nodes, so they never move when the display density changes.

Detail

Every corner point of a body — the exact points, not mesh nodes, so they never move when the display density changes. Each carries how many edges meet there: three at a box's corner, two where a cylinder's seam ends. This is what to snap a dimension to, measure between, or hand a construction that wants a point in space — construct.plane type three_point takes three of these. There is no segments argument because a vertex has no length to discretise. A vertex ID is a durable identity, like fc: and eg:: it keeps naming the same corner through later features, and a corner an edit consumes leaves the list rather than renumbering the ones after it.

query.view_geometry kernel

The curves a drawing view draws, worked out NOW from the bodies it names - visible edges in one list, the ones the solid hides in another, and on a SECTION view the boundary of the cut in a third, because a print draws all three with different pens and hatches inside the last.

Detail

The curves a drawing view draws, worked out NOW from the bodies it names - visible edges in one list, the ones the solid hides in another, and on a SECTION view the boundary of the cut in a third, because a print draws all three with different pens and hatches inside the last. Nothing is stored and nothing goes stale: edit the model and ask again, and the answer has moved with it. Every curve is a line, circle, arc, ellipse or spline in the view plane's own millimetres, spelled exactly as query.sketch spells a 2D curve so anything that can draw a sketch can draw a print - but with no IDs, because a view's curves are a picture rather than entities anything can reference. THE SCALE IS REPORTED AND NOT APPLIED, and neither is the view's place on the page: these are the part's own millimetres, so a length measured off them is a length of the part rather than of the paper. Sharp edges and the outline are drawn; the smooth line where a fillet meets the face it blends into is not, because both ISO and ASME suppress it. The view's dimensions come back MEASURED here too - each with the number it states, worked out now, the two points its extension lines run from, and the LABEL the print draws: text, the number to its stored precision with its prefix and any ±tolerance, and stack, null or the pair written after it (the two deviations, reduced; or the two limits, full height); a dimension carrying an ISO 286 class also answers fit - the class's two deviations at the size just measured, in millimetres, or two nulls and a reason when the table does not state the class at that size; a dimension whose corners have left the model is answered with a null value and dangling true, kept on the sheet to be reattached rather than silently dropped. The view's annotations come back beside them, each with the words it says and where each of its leaders lands in this picture; a note's text is STORED rather than worked out, so a note whose corners have left the model is answered dangling and STILL CARRYING ITS OWN WORDS - which is the difference from a dimension, and is what lets a person read what a broken note was for before reattaching it. A general note points at nothing, so it has no leaders and can never dangle. A BROKEN view answers the shortened picture: the run between the break's from and to is gone, everything beyond it has slid back, breakLines says where each cut falls and how far across the part it reaches, broken and brokenBy say the band and the view that owns it - and every dimension's value was measured BEFORE the break, so a length across it is the part's. A BROKEN-OUT view answers the picture with its pocket cut in: the floor's boundary in cut, to hatch, the window's edge where it crossed material in breakoutBoundary, to draw thin, and breakout the pocket itself - a detail of such a view answers its parent's. And the corners come back too - every vertex of every body this view draws, with the vx: that names it in the MODEL, where it lands in this picture in the same millimetres as the curves, and how far into the picture it sits so that two corners one behind the other can be told apart. That list is how a click on a drawn corner becomes something drawing.add_dimension can measure between: the curves carry no IDs and never will, so this is the only way from the picture back to the part. A callout is the one annotation whose words are DERIVED rather than stored - off the hole or thread feature it names - so its text comes back HERE and not on query.drawings, with one leader landing per hole the feature drilled; and holes lists every drilled point and threaded face of the bodies this view draws, with the ft: a callout names it by and the words it would print, which is how a click on a drawn hole becomes a callout. circles lists every circular edge of those bodies - a hole's rim, a cylinder's end, a fillet's arc - with the eg: a radial or diameter dimension names it by, where its centre lands in this picture, its radius, and the shape of its projection (the unit direction it is widest in and the minor-over-major ratio: 1 seen true-shape, 0 seen edge-on), so a click on a drawn rim becomes a diameter. edges lists every STRAIGHT edge of those bodies with the eg: a linear dimension names it by and where its two ends land in this picture, so a click on a drawn line becomes its length: drawing.add_dimension takes that one eg: alone as a shorthand for the edge's two corners. A radial or diameter dimension's value is the MODEL's radius or diameter in every view, and its two points run from the centre to the rim (radial) or across the widest diameter (diameter). An angular dimension's value is the angle in DEGREES at its first corner between the rays to the other two, as this view draws them, and its three points are those corners in that order - the apex first; a side lying along the line of sight has no direction here, so the value is null with dangling false and the points still answered.

query.wall_thickness kernel

How thick the wall is behind each face of a body — the check that says whether a shelled, cast or moulded part is thin anywhere, and which face is thin.

Detail

How thick the wall is behind each face of a body — the check that says whether a shelled, cast or moulded part is thin anywhere, and which face is thin. One row per face, in the same order query.tree lists them, each carrying the least and greatest thickness measured over that face in MILLIMETRES. minThickness is the number to compare against what the process needs: there is no threshold argument, because this read must be answerable before anybody has decided what that is. Each measurement fires a ray from a point on the face along its inward normal — into the material — and takes the distance to the first face it meets, so on a tube's bore it reports the WALL and not the hole. Two things follow from that and both are facts about the answer, not caveats: it is a RAY thickness rather than a rolling-ball one, so where two walls are not parallel it reads LONG (a corner's true minimum runs across the diagonal, which the inward normal misses); and the face is SAMPLED on a grid rather than solved, so a thin spot smaller than the sampling can be missed and the true minimum may be SMALLER than what is reported. defined is false where nothing on that face could be measured — minThickness and maxThickness are then null. That happens when the body has no solid in it (a surface or wire body has no material side, so it has no wall thickness at all — measure across it with query.measure by naming its two faces instead), when every ray leaves the body without meeting a far wall, or when the face has no normal the sampler could read. Nothing is changed, nothing is recorded: this is a read.

Selection

The shared selection — one list the human and every connected AI point at together.

select.set

Set the shared selection — the one list the human and every connected AI point at together in the document this connection is on.

Detail

Set the shared selection — the one list the human and every connected AI point at together in the document this connection is on. Each open document has its own, so switching between them changes what is selected without selecting anything. Atomic: a call naming an entity that does not exist changes nothing at all. Send an empty list to clear it.

Camera & screenshots

The shared camera, and rendering it to an image — the AI’s eyes.

view.provide_image

A render provider answering a render.requested event.

Detail

A render provider answering a render.requested event. Not for general clients — the reply half of the screenshot round trip.

view.register_provider

Declare this connection able to draw images.

Detail

Declare this connection able to draw images. The core then routes view.screenshot to it (ADR 0007), and view.render to it when it says it can path-trace.

view.render

Path-trace the shared camera to a PNG — the photographic picture, where view.screenshot is the working one.

Detail

Path-trace the shared camera to a PNG — the photographic picture, where view.screenshot is the working one. Name a view instead to get that orientation framed on the whole model; name an explode or section state exactly as a screenshot does. Lit by a studio environment alone: a CoCAD document holds no lights. Costs seconds to minutes, not milliseconds, and the picture is a function of samples and bounces — the same numbers always give the same bytes. Served by a render provider that declares the render capability; the core never draws it itself.

view.screenshot

Render the shared camera to a PNG — set the view with view.set_camera, then shoot it.

Detail

Render the shared camera to a PNG — set the view with view.set_camera, then shoot it. Name a view instead to get that orientation framed on the whole model. Name an explode state to get the assembly drawn pulled apart; omitted, the model is drawn assembled. Name a section state to get the model drawn cut open at its saved plane; omitted, the model is drawn whole. The two compose: offsets first, then the plane cuts where the bodies are drawn. Served by whatever render provider is connected; the core never draws it itself. With no document open there is nothing to draw and the call is refused, rather than answered with an empty frame.

view.set_camera

Point the shared camera — the one view the human and every connected AI looking at this document look through.

Detail

Point the shared camera — the one view the human and every connected AI looking at this document look through. Each open document has its own, so switching between them changes the view without moving any camera. A turntable: a target, a distance from it, a bearing and a height, so there is no roll. Session state, like the selection: never saved, never undone, and it changes no geometry. The person at the window sees every move you make here, so move the camera to SHOW them something, never as a routine step before a command or a screenshot - view.screenshot renders through the camera as it stands, and the person may have pointed it on purpose.

Session & application

Who is connected and what they may do: identity, pause and resume, preferences, and shutdown.

core.delete_fit_calibration

Forget one fit calibration, named by its printer, material and nozzle exactly as query.fit_calibrations reports them.

Detail

Forget one fit calibration, named by its printer, material and nozzle exactly as query.fit_calibrations reports them. A calibration that is not there is reported rather than ignored, because the likeliest cause is a typo. Nothing else in the file is touched. Not undoable and not in the timeline.

core.delete_printer desktop

Forget one printer, named exactly as query.printers lists it, and the key kept for it.

Detail

Forget one printer, named exactly as query.printers lists it, and the key kept for it. A printer that is not there is reported rather than ignored, because the likeliest cause is a typo. Nothing else in the list is touched. Not undoable and not in the timeline.

core.discard_recovery

Delete one crashed session's recording, for when a person has been offered it back and said no.

Detail

Delete one crashed session's recording, for when a person has been offered it back and said no. CoCAD never removes a recording by itself - doc.recover leaves it where it is, because it is still the only copy of that work until the recovered document is saved - so this is the only way one goes. Succeeds when the recording has already gone, because the outcome the caller wanted is the outcome.

core.duplicate_document

Open a copy of the current document in a new tab and move this connection to it, leaving the original open and untouched.

Detail

Open a copy of the current document in a new tab and move this connection to it, leaving the original open and untouched. The copy is exactly what saving the document and opening the file would give, without a file: its recorded steps are replayed, so it has the same timeline and the same entity IDs, and the steps it was made from belong to nobody in this launch - undoing one asks for confirmation, as it does in a reopened file. It has never been saved, holds no file, is not read-only, and looks from where the original's tab was looking. Nothing is copied back: close it with doc.close to discard it, or save it with doc.save to keep it. firstFailure is present when a step did not replay, exactly as doc.open reports it. Other connections stay where they are.

core.identify

Say what this client is, so the human can see which timeline steps an AI made.

Detail

Say what this client is, so the human can see which timeline steps an AI made. Declared once per connection: a second call is refused. A client that never identifies is reported as an author of null, never guessed at.

core.install_mcp_config

Write CoCAD into one AI client's MCP configuration file, so nobody has to find that file and edit it by hand.

Detail

Write CoCAD into one AI client's MCP configuration file, so nobody has to find that file and edit it by hand. It MERGES: exactly one key is set - the cocad entry under mcpServers - and every other key, every other server and the order of both come back out unchanged, which is what otherServers in the reply counts. client is an id from query.mcp_setup's clients list and there is no path argument, so the only file this can write is one this core reported; a client whose transport is http is refused, because its entry is an address and a token rather than a launch. action reads created or merged, replaced says whether a cocad entry was already there, and backupPath is where the previous bytes went - null when there was no file. It refuses rather than guessing: NO_MCP_SERVER when this build has no server for a client to launch, CONFIG_UNREADABLE when the file exists and is not JSON, and in both cases the file is left exactly as it was. It says nothing about the open document, writes no history step and cannot be undone - restart the AI client afterwards for it to read the new configuration.

core.pause

Hold AI edits so the human can inspect or take over.

Detail

Hold AI edits so the human can inspect or take over. Queued, not killed — held commands run when core.resume lifts the pause.

core.resume

Lift the pause and run everything it held, in the order it arrived.

Detail

Lift the pause and run everything it held, in the order it arrived. Refuses another client's pause unless confirm is true.

core.set_fit_calibration

Record what one printer actually makes: print a coupon of holes and pins, measure them with calipers, and send the designed and measured diameters here.

Detail

Record what one printer actually makes: print a coupon of holes and pins, measure them with calipers, and send the designed and measured diameters here. The calibration is named by printer, material and nozzle together - PLA and PETG on one printer are two calibrations - and sending the same three again REPLACES that calibration's readings whole, because a new sitting with the calipers describes the machine as it is now. At least one reading is needed. Names are used exactly as sent: one with a leading or trailing space is refused rather than trimmed. The reply carries the line through each list, as query.fit_calibrations reports it. Readings that say a bigger size printed smaller are refused - the likeliest cause is two readings typed into each other's rows. Kept beside your documents rather than in one, so it is not undoable and not in the timeline.

core.set_preferences

Change application preferences — camera, sketch and display units.

Detail

Change application preferences — camera, sketch and display units. Atomic: a call with a bad key or an out-of-range value changes nothing at all. null restores a default.

core.set_printer desktop

Add a printer CoCAD can send to, or change one.

Detail

Add a printer CoCAD can send to, or change one. name is yours to choose and identifies it: sent again, the same name REPLACES its kind and host. kind is the local API it speaks - octoprint, prusalink (Prusa's API on the printer itself, not the Prusa Connect cloud), moonraker (Klipper) or bambu (LAN mode). host is its address on your network, e.g. 192.168.1.40 or octopi.local, with an optional :port and no http://. key is the API key (OctoPrint, PrusaLink, Moonraker) or the LAN access code (Bambu): it is kept in Windows Credential Manager, never in a CoCAD file and never in any reply - leave it out to keep the one already stored, or send an empty string to forget it. CoCAD connects only to the address you give and holds no cloud account. A Bambu printer is reached while it is saved and the certificate it shows is TRUSTED for it from then on (certificate in the reply: its sha256 fingerprint, its serial and its issuer); a different certificate later is refused by name before the access code is sent. A certificate issued by a program inspecting the connection (an antivirus's HTTPS scanning) is refused with what to exclude. To trust a printer's NEW certificate after a printer swap or a firmware update, send its fingerprint as certificate, exactly as query.printer_reachable reports it. detail says what happened to a Bambu printer's certificate in one sentence. Not undoable and not in the timeline.

core.set_shortcuts

Move a keyboard shortcut onto another key.

Detail

Move a keyboard shortcut onto another key. Atomic: a call naming an unknown action, an unwritable key, or a key another action already answers in the same place changes nothing at all. null restores that action's shipped key. Because the whole call is judged together, two actions can SWAP keys in one send - which is the only way to swap them, since either half alone would collide with the other. A key is written unspaced with the modifiers Ctrl, Alt and Shift first, in that order, then the key; Esc cannot be bound to anything. query.shortcuts lists every action with the key it ships with and the key it has now.

core.set_thumbnail

Remember the preview picture for a document, so Open Recent and the template gallery can show what it looks like.

Detail

Remember the preview picture for a document, so Open Recent and the template gallery can show what it looks like. CoCAD's own window sends one after every save; any client with a viewport can. The picture is a cache beside the recent list and is NOT part of the .cocad file - a document sent to somebody else arrives with no preview and grows one the first time they save it, which is why a preview can never disagree with the drawing. The newest files.recentCount of them are kept, so turning the recent list off forgets the pictures too - EXCEPT for a document that is on the template shelf, whose picture is kept for as long as the template is, because nothing puts a template in the recent list. The reply's pinned says which of the two happened.

core.shutdown --allow-remote-shutdown

Stop the core gracefully, removing its discovery file.

Detail

Stop the core gracefully, removing its discovery file. Enabled only when the core was launched with --allow-remote-shutdown. Declined - stopping false, attachedWindows saying how many - while another CoCAD window is attached to this core, because closing one window must not end the session another is still drawing; the last window's close is the one that stops it.

core.switch_document

Make one of the open documents the one this connection acts on, so every later command on this connection is about it.

Detail

Make one of the open documents the one this connection acts on, so every later command on this connection is about it. Only this connection moves - another client stays where it was, which is what stops a person changing tabs from redirecting an AI's next command into a part nobody chose. Switching to the document you are already on changes nothing. List what is open with query.documents.

core.take_lock

Take the write lock on the file this document was opened from, for a person who has checked that nobody else has it.

Detail

Take the write lock on the file this document was opened from, for a person who has checked that nobody else has it. A document opened while another CoCAD held its file is read-only: it draws, measures, sections and exports as usual, and saving it writes beside the original rather than over it - so this is the way back, and the alternative to deleting a .lock file by hand. A lock nobody holds, or one a CoCAD on this machine left behind when it crashed, is taken without force; force is what takes one a live CoCAD still holds, which is a judgement only somebody who has confirmed the holder is gone can make. Answers readOnly and lockedBy as doc.open does, plus taken - whether this call got it - and displaced, naming whoever had it when force took it from them. A document open in another tab of this CoCAD is refused rather than taken over, because the remedy is to close that tab; a document that has never been saved has no file to lock.

Assemblies

Components, joints, standard parts, and saved explode, section and display states.

assembly.create_component kernel

Turn bodies and placements that are already in this document into a component - a part with an identity of its own, which a later command can place again elsewhere or insert into another document.

Detail

Turn bodies and placements that are already in this document into a component - a part with an identity of its own, which a later command can place again elsewhere or insert into another document. Nothing is copied and nothing is created: the bodies keep their IDs, their faces and everything built on them, and simply move out of the Bodies folder and into the new component's occurrence in query.tree. Name placements as well as, or instead of, bodies to build a SUB-ASSEMBLY: the parts you name move inside the new component and stay parts in their own right, so a hinge made of two knuckles and a pin still lists all three. One component is created and placed once; placing more of the same part is a separate command. Name the members explicitly - unlike query.copy and export.step, omitting both lists is refused rather than meaning every body. Undo puts everything back exactly as it was.

assembly.create_explode_state

Save a named way of drawing this assembly pulled apart - what an instruction sheet needs and what a screenshot can later be taken through.

Detail

Save a named way of drawing this assembly pulled apart - what an instruction sheet needs and what a screenshot can later be taken through. Nothing about the model changes: the bodies stay exactly where they are, so query.measure, query.tessellate and every export keep answering the assembled part, and a state is a picture rather than a pose. Name bodies, or component placements (each contributing every body under it, nested sub-assemblies included), and the displacement to draw them at - millimetres in the document's own axes, so {"z": 50} lifts a lid off a box. What you name is unioned, so a body named directly and also inside a placement you named gets one offset. Send no bodies at all to create an empty state you fill in afterwards. A document may hold as many states as you like and nothing records which one is showing - that belongs to whoever is looking, exactly as a camera does. Saved with the file. Not undoable and not in the timeline: arranging a picture is not a modelling step, and twenty parts dragged apart must not become twenty features. Joints, welds and grounding are all ignored here, because every one of them constrains MOTION and nothing is being moved - pulling six bolts out of the plate they are welded to is exactly the picture this exists to draw.

assembly.create_interference_body kernel

Turn a clash into a body you can measure and model against.

Detail

Turn a clash into a body you can measure and model against. Name the two bodies of a pair query.interference reported and this makes a new body of exactly the material they share - the same solid that check measured, kept this time instead of thrown away. It is an ordinary body from that moment on: query.measure gives its volume and centre of mass, you can export it, section it, or use it as a cut tool to take the clash out of one of the parts. This is how you answer "how much do I have to shave off?" rather than just "they overlap by 500 cubic millimetres". Nothing is consumed: both original bodies are left exactly as they were. The new body is loose in the document unless both parts are in the SAME component placement, in which case it is born inside that placement too - material shared by two different parts belongs to neither, and filing it under one of them would be a claim about which one owns the overlap. It enters the timeline like any other feature, so Ctrl+Z removes it. Two bodies that only touch, or that do not meet at all, are refused: a contact has a surface and no substance, so there is nothing to make.

assembly.create_joint kernel

Join two component placements so one is positioned by the other - the command that turns a pile of parts into an assembly.

Detail

Join two component placements so one is positioned by the other - the command that turns a pile of parts into an assembly. The CHILD is carried onto the PARENT and the parent never moves, so build outwards from whatever is grounded. Each part says where the joint sits on it by naming one of its own faces: a flat face gives its centre and its normal, and a cylindrical one gives a hole's axis - so a pin into a bore is one call, and it is the usual way to make a revolute joint. Seven types: rigid welds the two together, and the other six each leave one, two or three degrees of freedom that assembly.set_joint_value can later drive. Fine-tune the fit with offset (millimetres, measured in the parent origin's own axes, so it follows the part when the part turns), angle (degrees about the joint axis) and flip (turn the child over) - or send asBuilt to read all three off where the parts already stand and move nothing at all. The whole child placement moves, including everything nested inside it, so a sub-assembly arrives in one piece and every fc:, eg: and vx: on it survives. The two faces are remembered rather than the positions they work out to, which is what makes a joint hold when you go back and change an earlier feature. A placement can have only one parent joint, and a loop is refused: this build poses a tree of parts, not a linkage. Ground the part you want fixed with assembly.set_grounded rather than jointing it to the world. To place a part against another WITHOUT holding it there - the same mate arithmetic as one plain undoable move, with nothing remembered - use feature.align instead; it takes a loose body as readily as a placement.

assembly.create_named_view

Save the picture - a named view: one camera plus what is showing, to return to later.

Detail

Save the picture - a named view: one camera plus what is showing, to return to later. Stores the camera you SEND (the five channels query.camera answers - the core deliberately never reads the shared camera for you, so a saved view cannot depend on what a window happened to be showing), a display style, optionally which section state cuts the picture and which explode state arranges it, and the entities the picture hides. Applying a view is a composition you make: view.set_camera with the stored camera, and doc.set_visible for the hidden set - there is deliberately no apply command, because a journaled apply would repoint every reader's camera when the file reopens. Nothing about the model changes: query.measure, query.tessellate and every export keep answering the whole part. Saved with the file. Not undoable and not in the timeline: choosing a picture is not a modelling step. Nothing global records which view is showing - that belongs to whoever is looking, exactly as a camera does.

assembly.create_rigid_group kernel

Weld two or more component placements into one movable unit, exactly as they now stand.

Detail

Weld two or more component placements into one movable unit, exactly as they now stand. Move any member and every member travels with it; nothing moves when the group is made. This is how you say "these six bolts travel with the plate" without making six joints - a group needs no faces, has no parent and no child, and imposes no direction. A placement is in at most one group, and two placements a chain of joints already connects cannot be welded, because that would close a loop this build has no solver to satisfy. Grounding any member fixes the whole group. Undo it with feature.suppress on the featureId it returns.

assembly.create_section_state

Save a named cutting plane through this model - a section view, the picture an engineer cuts to inspect a bore or a wall thickness.

Detail

Save a named cutting plane through this model - a section view, the picture an engineer cuts to inspect a bore or a wall thickness. Nothing about the model changes: the cut is composed at draw time, so query.measure, query.tessellate and every export keep answering the whole part, and a state is a picture rather than an operation. Give one plane as a point on it and a normal - millimetres in the document's own axes - and material on the side the normal points to is cut away, so the exposed face of what remains looks at a viewer standing in the removed half. Negating the normal flips the cut; there is no flip flag. The plane is required: a section state with no plane would draw nothing and mean nothing, which is where this differs from an empty explode state. A document may hold as many states as you like - "Through the bore" beside "Down the centreline" - and nothing records which one is showing: that belongs to whoever is looking, exactly as a camera does. Saved with the file. Not undoable and not in the timeline: choosing a picture is not a modelling step, and a plane dragged twenty times must not become twenty features. The cut applies to the drawn model only - sketches, grids and marks are never cut, and it composes with an explode state: offsets first, then the plane cuts where the bodies are drawn.

assembly.delete_display_state

Delete a saved display state - an explode state ("ex:1"), a section state ("sx:1") or a named view ("nv:1").

Detail

Delete a saved display state - an explode state ("ex:1"), a section state ("sx:1") or a named view ("nv:1"). One command for the three kinds because deletion is the same act for all of them, where creation is not. Deleting is journaled and saved but NOT undoable - a deleted state is gone; read it back first (the matching query) if you are unsure. A state a named view references is refused by name: delete or update the view first, so a saved view never changes what it shows without anybody being told.

assembly.insert_component kernel

Insert another CoCAD document into this one as a component - the usual way to build an assembly out of parts that were modelled separately.

Detail

Insert another CoCAD document into this one as a component - the usual way to build an assembly out of parts that were modelled separately. The file's own recipe is replayed here, so its bodies arrive as they were built and the part keeps an identity of its own: assembly.place_component puts down further copies of it, and doc.rename relabels every copy at once. It arrives at the coordinates the source document built it at, so move it where you want with feature.move on the occurrence this reply names, which slides the whole placement and everything nested under it. By default the part is EMBEDDED - this document keeps its own copy, so it still opens on a machine that has never seen the file. Send link if you would rather this document re-read the file every time it opens, which is what you want when somebody else owns the part and is still changing it. Use assembly.create_component instead to make a component out of bodies that are already here. If the file is itself an assembly, its inner structure arrives with it: every part inside it becomes a component of this document too, placed inside the one this call creates, so query.tree shows the whole tree the source document had. The part-metadata travels too: the file's own record - part number, description, material and the rest - becomes the new component's, and a nested member arrives with its record, so query.bom's columns are filled the moment the part lands.

assembly.insert_standard_part kernel

Place a bought standard part - a socket head cap screw, a hex nut, a plain washer, a heat-set insert or a ball bearing - sized from the SAME row of the hole table that the hole wizard drills from, so the hole and the hardware always agree (query.hole_standards shows each size's hardware, and an insert's or bearing's row is the part).

Detail

Place a bought standard part - a socket head cap screw, a hex nut, a plain washer, a heat-set insert or a ball bearing - sized from the SAME row of the hole table that the hole wizard drills from, so the hole and the hardware always agree (query.hole_standards shows each size's hardware, and an insert's or bearing's row is the part). The part arrives as a COMPONENT named by its designation (ISO 4762 M3 x 10, ISO 4032 M3, ISO 7089 M3, ruthex RX-M3x5.7, 608 bearing), and a second insert of the same designation places another copy of that same component, so query.bom counts six screws on one row rather than six parts. It is built with its axis on +Z through origin and the face that seats against the work at that height: a screw's head stands above and its shank goes down into the work; a heat-set insert goes down into its hole with its top flush; a nut, a washer and a bearing stand above. So send a hole's entry point as origin and the part sits in it; turn it any other way with feature.move or a joint afterwards. Threads are COSMETIC (feature.thread inside the part's own recipe, recorded and not cut) at the coarse pitch. Deliberately not modelled: chamfers and fillets on heads and nuts, an insert's knurl, a bearing's balls, races and shields. Parts come from CoCAD's SHIPPED table only, never from a hole-standards.json of your own, so a document rebuilds the same part on every machine. One undo takes it back.

assembly.mirror_component kernel

Mirror a placed component in a plane and get the OPPOSITE HAND version of it - a new component in its own right, placed where the reflection lands.

Detail

Mirror a placed component in a plane and get the OPPOSITE HAND version of it - a new component in its own right, placed where the reflection lands. This is deliberately not another copy of the same part: a reflection swaps handedness, so a left-hand bracket and a right-hand bracket are two different parts and a parts list has to say so (feature.pattern repeats a placement, which is the other question). The plane is a base plane, a planar face or a construction plane - the same three things a sketch can be drawn on - and the placement being mirrored is never touched. If it is a sub-assembly, its structure comes with it: every part inside becomes a mirrored component of its own, nested under the new placement exactly as it was under the old one, so a mirrored hinge is still a hinge made of knuckles. There is no geometric refusal: a reflection is an isometry, so a plane straight through the part is fine and so is the part's own plane of symmetry. Of the part-metadata, description, material and custom fields copy across; partNumber, revision and excludeFromBom deliberately do not - an opposite hand part is a different part, so give it its own part number with doc.set_metadata.

assembly.place_component kernel

Place another copy of a component that already exists in this document.

Detail

Place another copy of a component that already exists in this document. The new placement gets its own bodies, built from the component's own stored recipe, so editing one copy does not change the others - CoCAD keeps them the same part by identity rather than by sharing geometry. It arrives at the same coordinates as the original, on top of it: move it where you want with feature.move on the occurrence this reply names, which slides the whole placement and everything nested under it, exactly as you would after feature.paste. query.tree shows every placement in the Placements folder, each with an ordinal - Bracket 1, Bracket 2 - and all of them read the component's name, so renaming it with doc.rename relabels every copy at once. Use assembly.create_component to make a component out of bodies you already have. If the component is itself an assembly, its inner structure comes with it: the parts inside it arrive as placements of their own, nested under the new one in query.tree, so a hinge placed twice gives you two hinges each with its own knuckles.

Point every linked component that reads one file at a different file, and rebuild the document from its own recipe.

Detail

Point every linked component that reads one file at a different file, and rebuild the document from its own recipe. This is how a part whose file was moved or renamed is put back: call query.links for the path the recipe stores, then send that path as from and the file's new home as to. Every record naming from is repointed, so a part placed twice is repaired once. from is matched exactly against the stored string, so send it back as query.links reports it rather than a tidied-up version of it. from and to may be the same, which is how you tell CoCAD that a file it could not find has been put back where it belongs. The whole document is replayed against the new file, so a part that has changed shape carries every later feature with it - and nothing changes at all unless the whole rebuild finishes: a file that cannot be read leaves the document exactly as it was and names what refused. The reply says how many records were repointed and whether the change can be undone. Repairing a link that was BROKEN cannot be undone, because the state it came from is a document with a part missing and this build will not construct one; repointing a link that was working can be, and doc.undo puts the old file back.

assembly.replace_component kernel

Swap the part in a placement for another component, keeping the placement where it is.

Detail

Swap the part in a placement for another component, keeping the placement where it is. The new part goes exactly where the old one sits relative to its own design - if the old part was moved 50 mm and turned 90 degrees from where its file built it, the new one is moved and turned the same way - so two versions of a part modelled at the same origin swap in place. The placement keeps its id, its grounded flag, its paint and every joint: a joint carries across when the new part has a face of the same kind (flat or round) giving the same joint position and direction, and is re-pointed to it with nothing moving; when it has none, the swap is refused and names the joint - send it in dropJoints to delete it with the swap instead, or (when the placement is the joint's child) in resolveJoints to move the new part onto its nearest face of the same kind. The new part is a component of this document, or a .cocad file (path or content), which becomes a new component in the same step; either may be a sub-assembly, whose parts are placed inside the placement, all moved together. A placement that is itself a sub-assembly is replaced whole, the parts inside it retired with it. The old bodies are replaced by new ones (the reply lists both). One timeline feature and one undo; feature.edit can swap it again and feature.suppress puts the old part back.

assembly.set_explode_offset

Change where bodies are drawn inside an explode state you already have - or put them back home.

Detail

Change where bodies are drawn inside an explode state you already have - or put them back home. Name the state, name bodies or component placements (each contributing every body under it, nested sub-assemblies included), and give the offset to draw them at. A body that already has an offset in this state has it replaced, and a body that has none gets one, so this is how a part is nudged, re-aimed, or added to an arrangement one at a time. Send "offset": null to CLEAR - the body goes back to being drawn where it lives, which is the same thing as never having been offset. Leaving offset out entirely is refused rather than treated as null, so a forgotten field cannot quietly erase an arrangement. The offset is absolute and not a nudge: it says where the part is drawn, not how much further to move it, so sending the same call twice draws the part in the same place. Nothing about the model changes - the bodies stay exactly where they are, and query.measure, query.tessellate and every export keep answering the assembled part. Saved with the file. Not undoable and not in the timeline, for the same reason the state itself is not: arranging a picture is not a modelling step.

assembly.set_grounded kernel

Fix placements in space, or free them again.

Detail

Fix placements in space, or free them again. A grounded placement is one you have said must not move: feature.move refuses any body inside it, so the part stays where it is while everything else is positioned around it - which is how an assembly gets a fixed reference to build against. Name placements ("oc:1"), not components: two copies of one part can differ, and usually should. Sets rather than toggles, so sending the same call twice is not two different requests, and the reply says how many actually moved. Unlike hiding, this IS undoable - grounding says which parts are fixed, so it is part of what the model means rather than a way of looking at it. query.tree reports it as grounded on every row in the Placements folder.

assembly.set_interference_ignored kernel

Tell this document that two bodies overlap on purpose, so query.interference stops reporting them - or take that back.

Detail

Tell this document that two bodies overlap on purpose, so query.interference stops reporting them - or take that back. A press fit, a moulded-in boss, a weld bead: real assemblies are full of clashes somebody designed, and without this the check answers the same list of known ones every time and the real problem hides among them. The pair is two BODIES rather than two placements, because that is what shares the material: ignoring bd:3 against bd:7 leaves every other body of the same two parts still checked. Order does not matter, and ignoring a pair that is already ignored is not an error - it simply reports changed: false. This IS part of the model rather than a way of looking at it, so it is undoable and it is saved with the file. query.interference lists what is being suppressed in ignored, so nothing is ever hidden without saying so.

assembly.set_joint_value kernel

Drive a joint - swing a hinge open, slide a piston, turn a shaft - and carry everything jointed below it.

Detail

Drive a joint - swing a hinge open, slide a piston, turn a shaft - and carry everything jointed below it. Every value is measured from the pose the joint was CREATED in, so 0 is always where you built it; it is absolute rather than a step, so sending the same value twice does nothing the second time and driving back to 0 puts the part exactly where it started. A joint with ONE degree of freedom takes value, a bare number; one with several takes values, a list with one number per freedom in the order its type lists them - a cylindrical joint takes [turn in degrees, travel in millimetres]. values works for every kind, so a caller that always sends the list never has to special-case. Only a rigid joint has nothing to drive, and it is refused here. Everything below the joint comes too - a bolt jointed to the arm you are swinging travels with the arm, however deep the chain goes - and the parent never moves. If the joint was given limits, a value outside them is refused rather than quietly pulled back inside, so what you asked for and what happened can never differ without your being told. The pose is part of the document: it is saved, undone with Ctrl+Z, and reproduced exactly when the file is opened again.

assembly.set_section_plane

Move a saved cutting plane - aim an existing section state somewhere else.

Detail

Move a saved cutting plane - aim an existing section state somewhere else. Name the state and give the whole plane, a point on it and a normal - millimetres in the document's own axes - and the stored plane is replaced wholesale. The plane is absolute and not a nudge: it says where the cut now is, not how much further to move it, so sending the same call twice cuts in the same place and a retry is safe. Material on the side the normal points to is cut away; negating the normal flips the cut, and there is no flip flag. Both fields are required even when only one changed - the plane travels whole, so a forgotten field is a refusal rather than a half-moved cut - and there is no null here: a state cannot be emptied of its plane, because a section state with no plane would draw nothing and mean nothing. Nothing about the model changes: query.measure, query.tessellate and every export keep answering the whole part. Saved with the file. Not undoable and not in the timeline, for the same reason the state itself is not: a plane dragged twenty times must not become twenty features.

assembly.update_named_view

Re-aim a saved view - replace fields of a named view, field by field.

Detail

Re-aim a saved view - replace fields of a named view, field by field. A field you send is replaced whole (the camera always arrives as all five channels); a field you leave out is kept, because a view's fields are independent facts and re-aiming the camera says nothing about the hidden set. Clearing is an explicit value, never an absence: section null makes the view uncut, explode null makes it assembled, hiddenIds [] makes it hide nothing. Sending the same call twice changes nothing the second time. Saved with the file; not undoable and not in the timeline, for the reason the view itself is not.

Drawings

Sheets, views, dimensions, annotations, balloons and GD&T symbols.

drawing.add_annotation kernel

Put an annotation on a drawing view - the marks a shop reads beside the numbers.

Detail

Put an annotation on a drawing view - the marks a shop reads beside the numbers. Eight kinds, chosen with kind: a NOTE (the default) is words, a CENTRE MARK is the cross at a round feature's centre, a CENTRELINE is the chain line between two corners, a SURFACE FINISH is the check-mark symbol with its value beside it, a WELD is the reference line and arrow with the weld's designation on the arrow side - the two symbols drawn the way the drawing's standard draws them, with the words stored exactly as sent - and a CALLOUT is the hole or thread callout, the one kind whose words are DERIVED: it names a feature.hole or feature.thread ("ft:<n>") and prints what that record says ("4X ⌀6.6 ↧12", "M6×1") on every read, so it can never state a hole the part does not have; a BALLOON is the circled item number of an assembly drawing, the second derived kind - it names one corner of a part and prints that part's row number from query.bom, so it can never disagree with the parts list; and a BEND CALLOUT is the third, the UP or DOWN, the angle and the inside radius written beside a fold line on a flat-pattern view - it names the bend's inner face ("fc:<body>.<n>") and reads the words off the blank's own bend line, so it says exactly what the bend chart says. A note's TEXT IS STORED EXACTLY AS SENT, which is the deliberate opposite of a dimension: a dimension's number is a measurement of the part and is worked out afresh on every read, where a note is a statement you made and there is nothing in the model to derive it from. A note points at as many corners of the part as you like, with a leader line running to each - or at NONE at all, which is a general note, the kind that sits in a drawing's corner saying how the whole print is to be read; a centre mark takes exactly one corner and a centreline exactly two, and neither takes any text, because both draw themselves from the corners they name. The corners are named in the MODEL - "vx:<body>.<n>" - and not in the picture, which is what makes the mark survive a recompute; a corner removed later leaves it in place, marked dangling and still carrying its own words, to be reattached rather than vanishing off the sheet. x and y are where the text sits, in the view's own millimetres. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry, no mass and no export.

drawing.add_balloons kernel

Balloon a whole view at once - the auto-balloon of an assembly drawing, and P5B-6's add_balloons.

Detail

Balloon a whole view at once - the auto-balloon of an assembly drawing, and P5B-6's add_balloons. One balloon per PLACEMENT the view draws that is on the parts list and has no balloon yet, each pointing at that placement's topmost corner in the picture and standing off it up and to the right by standoff millimetres ON THE SHEET (10 by default, converted by the view's scale, because a standoff is a drafting distance and not a model one). Two placements of one part get two balloons with one number, which is how an assembly print reads. A placement already ballooned on this view is left alone, so sending this twice fills in what a person did by hand and moves nothing; a part excluded from the BOM gets none, because a balloon with nothing to say is not worth minting; loose bodies are not placements and get none. Each balloon is an ordinary annotation afterwards - drag it with drawing.set_annotation, remove it with drawing.remove_annotation - and the whole set is ONE undo step. A view with nothing to balloon answers an empty list and is not an error.

drawing.add_dimension kernel

Measure the part on a drawing view - the number a shop cuts to: between two corners (aligned, horizontal or vertical), a corner's signed coordinate from an origin corner (ordinate_x, ordinate_y - a baseline set is several of the linear kinds sharing their first corner), a circular edge's radius or diameter, or the angle at a corner between two others (angular, in degrees).

Detail

Measure the part on a drawing view - the number a shop cuts to: between two corners (aligned, horizontal or vertical), a corner's signed coordinate from an origin corner (ordinate_x, ordinate_y - a baseline set is several of the linear kinds sharing their first corner), a circular edge's radius or diameter, or the angle at a corner between two others (angular, in degrees). THE VALUE IS NEVER STORED: the dimension records what it measures, and query.view_geometry works the number out afresh every time it is asked, so editing the model moves the print with nothing to regenerate and a drawing can never state a length the part does not have. The operands are named in the MODEL - "vx:<body>.<n>" corners, or an "eg:<body>.<n>" edge: a circular one for a radius or diameter, a STRAIGHT one named alone on a linear kind as a shorthand for its two ends, or two straight edges meeting at a corner on an angular kind as a shorthand for the three corners - and not in the picture, which is what makes the dimension survive a recompute; one removed later leaves the dimension in place and marked dangling, to be reattached, rather than vanishing off the sheet. x and y are where the text sits, in the view's own millimetres. A tolerance (±0.1, +0.1/-0.05, the two limits, or an ISO 286 class such as H7 whose deviations the table gives at the measured size) and a decimal precision may be stated with it - both are STORED, because nothing in the model knows how much a shop may miss by - and query.view_geometry answers the label they produce, in the document's own unit (query.documents' units), with the other system's number bracketed beside it when dualUnits is true. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry, no mass and no export.

drawing.add_gdt kernel

Put a GD&T symbol on a drawing view - a DATUM feature symbol (the boxed letter on a leader ending in a triangle at the feature it names) or a FEATURE CONTROL FRAME (the row of boxes a shop reads as a geometric tolerance: the characteristic's symbol, the tolerance zone with ⌀ for a cylindrical one and Ⓜ or Ⓛ after it, then up to three datum references).

Detail

Put a GD&T symbol on a drawing view - a DATUM feature symbol (the boxed letter on a leader ending in a triangle at the feature it names) or a FEATURE CONTROL FRAME (the row of boxes a shop reads as a geometric tolerance: the characteristic's symbol, the tolerance zone with ⌀ for a cylindrical one and Ⓜ or Ⓛ after it, then up to three datum references). Everything it says is STORED - the letter, the characteristic, the tolerance in millimetres, the modifiers, the references - because every one is a person's claim about the part and nothing in the model could derive it; what query.view_geometry adds is where each leader lands, whether it still resolves, the printed cells and which referenced datum letters the drawing carries no symbol for. The fourteen characteristics decide the grammar: form tolerances take no datum, orientation and runout require one, a ⌀ zone and a material-condition modifier are legal only where the standards allow them - a frame that can never be right is refused saying why. A datum references by LETTER: a frame may name datum B before a datum B exists, and prints that cell amber until it does. A datum names exactly one corner ("vx:<body>.<n>") and a frame any number or none - a frame beside a dimension is the commonest placement on a print. x and y are where the box's lower-left corner sits, in the view's own millimetres. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry, no mass and no export.

drawing.add_sheet

Add a sheet to a drawing - one page of the print, the thing views get placed on.

Detail

Add a sheet to a drawing - one page of the print, the thing views get placed on. Say which size, either by name from query.sheet_sizes ("iso-a3", "ansi-b") or as width and height in millimetres for a size that is not listed; left out, it is A4 landscape. orientation says which of the two lengths is the width, so a size and an orientation together describe any page. A sheet stores the two lengths rather than a size name, so its page can never change because a machine's size table did. scale is the sheet's default drawing scale as one number - the drawn length over the model length, 1 for full size, 0.5 for 1:2, 2 for 2:1 - and it is what views placed here will use unless they say otherwise. The sheet is added at the end; drawing.set_sheet moves it. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry.

drawing.auxiliary_view kernel

Fold an AUXILIARY view off a view already on the sheet, about a planar FACE that view sees on edge - the way a print shows the true shape of a chamfer, a drafted wall or an angled cut that no front, side or top view sees square on.

Detail

Fold an AUXILIARY view off a view already on the sheet, about a planar FACE that view sees on edge - the way a print shows the true shape of a chamfer, a drafted wall or an angled cut that no front, side or top view sees square on. The new view looks straight at the face, so the face is drawn true-shape, and it is aligned to the view it is folded off along the face's own direction on that view's paper: on a third-angle drawing it sits on the side the face looks toward, on a first-angle drawing on the opposite side, offset millimetres away along that line. Turning or moving the parent turns and moves it; the hinge itself is worked out from the face ONCE and stored (query.drawings answers it as auxiliary.angle, degrees counter-clockwise from the parent's paper-right), and query.view_geometry says dangling when the face has since gone or leaned - send drawing.set_view auxiliary {face} to fold about it afresh. The face must be planar, on a body the parent draws, and seen as a LINE in the parent: a face the parent already sees square on needs no auxiliary, and one seen obliquely wants a secondary auxiliary view, which is not built yet. Nothing projects off an auxiliary, and an auxiliary of a section or a detail is refused. Undoable, and it is not a modelling step - no geometry, no mass and no export changes.

drawing.create

Start a drawing of this model - the 2D print a shop works from, and the thing a supplier package is made of.

Detail

Start a drawing of this model - the 2D print a shop works from, and the thing a supplier package is made of. A drawing lives inside this document and is saved with it, so opening the part opens its drawings and there is no second file to keep in step. Say which drafting standard it is drawn to - ISO or ASME - and, if the shop's convention differs from the standard's, which projection angle arranges its views; left out, the projection follows the standard, ISO being first-angle and ASME third-angle. A drawing carries no units of its own: dimensions read in the document's units, so a print always measures the same as the part. A document may hold as many drawings as you like - a machining print beside a weldment - each to its own standard. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry, no mass and no export. A new drawing has no sheets yet.

drawing.delete

Remove a drawing from this document, with everything on it.

Detail

Remove a drawing from this document, with everything on it. Nothing about the model changes - a drawing is a picture OF the part, so deleting one moves no geometry, no mass and no export. Undoable: one Ctrl+Z brings the drawing and its contents back exactly as they were, which is what makes this safe to offer at all.

drawing.detail_view kernel

Place a DETAIL view - an enlarged picture of one circular region of a view already on the sheet, the way a print shows a small groove or a thread relief that the main view draws too small to dimension.

Detail

Place a DETAIL view - an enlarged picture of one circular region of a view already on the sheet, the way a print shows a small groove or a thread relief that the main view draws too small to dimension. It looks exactly where the view it enlarges looks and follows that view when it is turned, but it is PLACED rather than aligned: x and y put it anywhere on the sheet, as a base view is put, because both drafting standards let a detail sit wherever there is room and the detail's name is the link. detail is the window - the centre and radius of the circle drawn on the view it enlarges, in THAT view's own millimetres, the same coordinates query.view_geometry answers its curves in; left out, a circle in the middle of what that view draws. The picture is what lies inside the circle, worked out with a real boolean along the line of sight, so a body behind a neighbour is still hidden by it and a detail of a SECTION view shows the cut and answers the cut's outline clipped to the circle. scale left out is TWICE the scale of the view it enlarges, live - rescale that view and the detail follows. Nothing projects off a detail, and a detail of a detail is refused: enlarge the first one's window instead. Undoable, and it is not a modelling step - a detail is a picture of the part, so no geometry, no mass and no export changes.

drawing.export kernel

CoCAD Pro only.

Detail

CoCAD Pro only. Write one drawing sheet to a file - the PDF a shop prints or the DXF another CAD or a plotter reads. The sheet is drawn exactly as the sheet canvas shows it: every view's visible edges (and its hidden edges, where the view draws them), a section's cut face outlined heavy and hatched, the section line and arrows on the view it was cut from, every dimension with its extension lines, arrowheads and number, every note, symbol, callout and balloon with its leader, every parts list with its rules and cells, and each view's caption. The PDF page is the sheet's own size in millimetres, so a 1:2 view prints at 1:2 with a rule laid on the paper - print to scale needs no dialog. The DXF puts the ink on named layers (VISIBLE, HIDDEN, CUT, HATCH, CENTER, SECTION, DIMENSIONS, ANNOTATIONS, TABLE, the sheet's edge on 0), in paper millimetres with the sheet's lower-left at the origin; dimensions are lines and text rather than DIMENSION entities, so a receiving CAD cannot re-measure the paper and print the wrong number. A dangling dimension prints ? and a dangling annotation prints its words, both in amber, so a print with a lost reference says so. Exporting changes nothing and cannot be undone; the file is written atomically and the reply says where the bytes landed and what was drawn. Set preview true to be told how big the file would be and what it would hold without writing anything. A CoCAD Free copy prints "CoCAD Free - non-commercial use" along the bottom of every sheet it exports.

drawing.flat_pattern_view kernel

Put the FLAT PATTERN of one sheet-metal part on a drawing sheet - the blank it is cut from, before anybody folds it, with a line down the middle of every bend.

Detail

Put the FLAT PATTERN of one sheet-metal part on a drawing sheet - the blank it is cut from, before anybody folds it, with a line down the middle of every bend. This is the drawing a laser or a punch works from, where drawing.place_view gives the drawing a person reads the folded part from. Say which sheet and which body; x and y put it on the page in millimetres from the sheet's lower-left corner, and left out it goes in the middle. scale is the drawn length over the model length and defaults to the SHEET's. There is no direction to choose: a blank is not a picture of the part from anywhere, so query.view_geometry answers direction null and says under flatPattern which FACE of the metal it is seen from. There is no hiddenLines or tangentEdges either - a blank is flat, and a developed sheet has no fillet to run out into anything. The part must carry a sheet-metal rule, because how much flat a bend eats depends on where the neutral axis sits inside the metal: build it with feature.base_flange or set one with doc.set_sheet_metal_rule. THE PICTURE IS NOT STORED: the blank is worked out from the part every time it is asked for, exactly as query.flat_pattern does and from the same code, so the sheet, the DXF and the read can never describe three different parts. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry, no mass and no export.

drawing.insert_bend_table kernel

Put a bend chart on a flat-pattern view - the table a press brake operator works from: one row per bend in the blank, numbered in the flat pattern's own order, each with whether the metal folds UP or DOWN away from the face you are looking at, the angle in degrees, the inside bend radius and the bend allowance.

Detail

Put a bend chart on a flat-pattern view - the table a press brake operator works from: one row per bend in the blank, numbered in the flat pattern's own order, each with whether the metal folds UP or DOWN away from the face you are looking at, the angle in degrees, the inside bend radius and the bend allowance. THE ROWS ARE NEVER STORED: the table records only where it sits on the page and which way it reads, and query.view_geometry works every row out afresh from the view's own bend lines, so changing a flange angle changes the print with nothing to regenerate. Every bend in the picture is also numbered beside its fold line. It must go on a FLAT-PATTERN view - place one with drawing.flat_pattern_view - because nothing else has bends to list, and because a flat-pattern view already names exactly one part. x and y are where the table's header row sits in the SHEET's millimetres - left out, the upper-left corner 10 mm in, rows reading down. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry.

drawing.insert_bom

Place a parts list - a BOM table - on a sheet.

Detail

Place a parts list - a BOM table - on a sheet. The table is a recipe, never a copy: it says where its header sits, which way its rows stack, which of query.bom's two modes it prints and which columns, and the rows are query.bom's on every read, so the table on the print can never disagree with the parts list the document answers and a balloon always names the row it points at. Left out, it prints partsOnly with item, quantity, partNumber, description and material, rows stacking upward from the header, in the sheet's lower-right corner 10 mm in from the right edge and clear of the title block's room - where a parts list sits over the title block, whether or not the sheet carries one yet. The reply's layout gives every column's printed label and paper width and the row height, which is what a client draws from. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry.

drawing.insert_hole_table kernel

Put a hole chart on a drawing view - the table a fixture plate or a bolt pattern is made from: one row per hole the view shows, each with a tag (A1, A2, B1 - lettered by size, numbered within the letter), its X and Y from one corner of the part, and its size.

Detail

Put a hole chart on a drawing view - the table a fixture plate or a bolt pattern is made from: one row per hole the view shows, each with a tag (A1, A2, B1 - lettered by size, numbered within the letter), its X and Y from one corner of the part, and its size. THE ROWS ARE NEVER STORED: the table records which corner is the origin and where it sits on the page, and query.view_geometry works every row out afresh from the holes the view draws, so drilling another hole or moving one changes the print with nothing to regenerate and a chart can never list a hole the part does not have. Every hole in the picture is also tagged beside its circle. x and y are where the table's header row sits in the SHEET's millimetres - left out, the upper-left corner 10 mm in, rows reading down. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry.

drawing.insert_revision_table

Place a revision table - a REV block - on a sheet.

Detail

Place a revision table - a REV block - on a sheet. Unlike a parts list or a hole chart, its rows are STORED: a revision is a person's words about the print - who changed what, when, and who signed it - and nothing in the model can derive them. Each row is rev and description with optional zone, date (YYYY-MM-DD) and approved, printed in the order sent; the five columns are ASME Y14.35's and cannot be chosen. Left out, the block is empty - the ruled block a first issue prints - with rows reading down from a header in the sheet's upper-right corner 10 mm in from both edges. The reply's layout gives every column's printed label and paper width and the row height, which is what a client draws from. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry.

drawing.insert_title_block

Place a title block on a sheet - the block in the lower-right corner that names the print.

Detail

Place a title block on a sheet - the block in the lower-right corner that names the print. Only five of its cells are stored, because only a person can say them: the company, who drew, checked and approved it, and the date of issue. Every other cell is DERIVED on every read and can never disagree with the document - the title (the document's description, or its name), the drawing number, material and revision from doc.set_metadata's record, the latest rev from the sheet's revision table when one has rows, SHEET n OF m from the sheet's place in its drawing, the scale, the size by name and the projection angle. A sheet carries exactly one; left out, it sits in the lower-right corner 10 mm in from both edges with every word empty. The reply's cells give each cell's label (ISO 7200's wording on an ISO drawing, ASME Y14.100's on an ASME one), value, place and size, which is what a client draws from. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry.

drawing.place_view kernel

Put a view of the model on a drawing sheet - the picture a shop reads the part from.

Detail

Put a view of the model on a drawing sheet - the picture a shop reads the part from. Say which sheet, which direction to look from (front, back, left, right, top, bottom or isometric; left out, front), and which bodies to draw - leave bodies out for every solid body in the document, which is what a view of the whole part wants and which keeps including bodies you add later. x and y put it on the page in millimetres from the sheet's lower-left corner; left out, the middle of the sheet. scale is the drawn length over the model length and defaults to the SHEET's, so changing the sheet's scale still moves every view that did not choose its own. hiddenLines says whether the edges the solid hides are drawn dashed; left out, they are not. tangentEdges says whether the smooth join where a fillet runs out into the face it blends into is drawn thin; left out, it is not, which is what ISO 128 and ASME Y14.2 ask for. THE PICTURE IS NOT STORED: the view records what to draw and query.view_geometry works out the curves each time it is asked, so editing the model updates the drawing with nothing to regenerate. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry, no mass and no export.

drawing.project_view kernel

Fold a second view off one already on the sheet - the side, top or bottom view a print is arranged from.

Detail

Fold a second view off one already on the sheet - the side, top or bottom view a print is arranged from. Say which view to project FROM and which side of it the new one sits on; which way it LOOKS follows from the drawing's projection angle, which is the whole difference between first-angle and third-angle drafting, so the side is the only thing there is to choose. THE CHILD IS LOCKED TO ITS PARENT: it draws the same bodies, at the same scale, aligned on the same line, and it follows when the parent is moved, turned or rescaled - so aiming a base view re-aims the whole arrangement with nothing to regenerate. offset is how far apart the two sit on the page; left out, they are spaced so the two pictures do not overlap. An isometric view projects nothing. Undoable, and it is not a modelling step: it adds nothing to the timeline and changes no geometry, no mass and no export.

drawing.remove_annotation kernel

Take a note off its view.

Detail

Take a note off its view. Nothing about the model changes - an annotation is a statement about the part rather than part of it, so removing one moves no geometry, no mass and no export. Undoable: one Ctrl+Z puts it back exactly where it was, saying exactly what it said.

drawing.remove_bend_table kernel

Take a bend chart off its view.

Detail

Take a bend chart off its view. Nothing about the model changes - the table stores no rows, so removing one loses nothing about the bends. Undoable: one Ctrl+Z puts it back exactly where it was.

drawing.remove_bom

Take a parts list off its sheet.

Detail

Take a parts list off its sheet. The sheet, its views and the model are otherwise untouched - a BOM table stores no rows, so removing one loses nothing about the parts. Undoable: one Ctrl+Z puts the table back exactly where it was.

drawing.remove_dimension kernel

Take a dimension off its view.

Detail

Take a dimension off its view. Nothing about the model changes - a dimension is a statement about the part rather than part of it, so removing one moves no geometry, no mass and no export. Undoable: one Ctrl+Z puts it back exactly where it was, measuring exactly what it measured.

drawing.remove_gdt kernel

Take a datum symbol or a feature control frame off its view.

Detail

Take a datum symbol or a feature control frame off its view. Nothing about the model changes. A datum other frames reference is removed all the same, and those frames report its letter missing on query.view_geometry and print that cell amber until a datum with the letter exists again. Undoable: one Ctrl+Z puts it back exactly as it was.

drawing.remove_hole_table kernel

Take a hole chart off its view.

Detail

Take a hole chart off its view. Nothing about the model changes - the table stores no rows, so removing one loses nothing about the holes. Undoable: one Ctrl+Z puts it back exactly where it was, measured from the same corner.

drawing.remove_revision_table

Take a revision table off its sheet.

Detail

Take a revision table off its sheet. The rows go with it - they are stored on the table and nowhere else - so this is the one table on a sheet whose removal loses words; undoable, and one Ctrl+Z puts the table back with every row exactly as it was.

drawing.remove_sheet

Take a sheet off a drawing, with everything placed on it.

Detail

Take a sheet off a drawing, with everything placed on it. The drawing and the model are otherwise untouched. Removing a drawing's last sheet is allowed: a drawing with no sheets is empty rather than broken. Undoable - one Ctrl+Z brings the sheet and its contents back exactly as they were, in the place they were in.

drawing.remove_title_block

Take a title block off its sheet.

Detail

Take a title block off its sheet. The five stored words go with it; the derived cells were never stored, so nothing about the document changes. Undoable, and one Ctrl+Z puts the block back with every word exactly as it was.

drawing.remove_view kernel

Take a view off its sheet.

Detail

Take a view off its sheet. THE VIEWS PROJECTED FROM IT GO WITH IT, and theirs: a projected view stores no aim and no place of its own, so an orphan would be a record with nothing to draw and nowhere to sit - the reply names every one that went. Their dimensions go with them, because a dimension is drawn on a view. Nothing about the model changes: a view is a picture OF the part, so removing one moves no geometry, no mass and no export. Undoable: one Ctrl+Z brings the whole family back exactly where it was.

drawing.section_view kernel

Fold a CUT view off one already on the sheet - the section a shop reads a part's inside from.

Detail

Fold a CUT view off one already on the sheet - the section a shop reads a part's inside from. It is drawing.project_view with a cutting plane: the same side, the same alignment, the same locked aim and scale, plus a line across the view it is cut from. Everything between the eye and that line is removed before the picture is drawn, and query.view_geometry answers a THIRD list of curves - where the plane met solid material, which is the outline a print draws heaviest and hatches inside. position is where the cut crosses the view it is projected from, in THAT view's own millimetres - the same coordinates query.view_geometry answers, so a number read off the picture is the number to send; left out, the cut passes through the middle of the part. A full section only: half, offset and aligned section lines need more than one number and are not built. An isometric view sections nothing. Undoable, and it is not a modelling step - the cut is a picture of the part, so no geometry, no mass and no export changes.

drawing.set_annotation kernel

Change what a note says, what it points at, or where its text sits - absolute values only, and any subset.

Detail

Change what a note says, what it points at, or where its text sits - absolute values only, and any subset. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. Sending entities is how a dangling note is reattached: name corners that exist and its leaders land again - and sending an EMPTY list is a real change, taking the leaders off and leaving a general note. Undoable, and it changes no geometry - an annotation is a statement about the part, not a shape.

drawing.set_bend_table kernel

Change where a bend chart sits on the sheet or which way its rows read - absolute values only, and any subset.

Detail

Change where a bend chart sits on the sheet or which way its rows read - absolute values only, and any subset. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. There is no origin to set: a bend's angle, radius and allowance are measured from nothing, so a bend chart has no datum corner and nothing about it can come adrift. Undoable, and it changes no geometry - a chart is a reading of the part, not a shape.

drawing.set_bom

Change where a parts list sits, which way its rows stack, which mode it prints or which columns - absolute values only, and any subset.

Detail

Change where a parts list sits, which way its rows stack, which mode it prints or which columns - absolute values only, and any subset. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. columns replaces the whole list when sent. Undoable, and it changes no geometry - a table is a recipe on a page, not a shape.

drawing.set_dimension kernel

Change what a dimension measures, which number it states, where its text sits, its tolerance, its precision or whether it prints dual units - absolute values only, and any subset.

Detail

Change what a dimension measures, which number it states, where its text sits, its tolerance, its precision or whether it prints dual units - absolute values only, and any subset. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. Sending entities is how a dangling dimension is reattached: name two corners (or one straight edge, meaning its two ends), one circular edge, or three corners on an angle (or two straight edges meeting at one), that exist and it measures again. A kind from another family (linear, circular, angular) must bring its entities with it. Undoable, and it changes no geometry - a dimension is a statement about the part, not a shape.

drawing.set_gdt kernel

Change what a datum symbol or a feature control frame says, what it points at, or where it sits - absolute values only, and any subset; absent fields are left exactly as they are, so a retry is always safe.

Detail

Change what a datum symbol or a feature control frame says, what it points at, or where it sits - absolute values only, and any subset; absent fields are left exactly as they are, so a retry is always safe. The call is judged as the record it PRODUCES: a characteristic that forbids the datums the frame already stores is refused naming them, and the fix is to send both in one call. Sending entities is how a dangling symbol is reattached; sending an empty list on a frame takes its leaders off. Turning a datum into a frame needs a characteristic and a tolerance in the same call. Re-lettering a datum other frames reference is allowed - those frames report the old letter missing. Undoable, and a call that changes nothing records no step.

drawing.set_hole_table kernel

Change which corner a hole chart measures from, where it sits on the sheet or which way its rows read - absolute values only, and any subset.

Detail

Change which corner a hole chart measures from, where it sits on the sheet or which way its rows read - absolute values only, and any subset. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. Sending origin is how a dangling chart is reattached: name a corner that exists and every X and Y reads again. Undoable, and it changes no geometry - a chart is a reading of the part, not a shape.

drawing.set_revision_table

Change where a revision table sits, which way its rows stack, or its rows - absolute values only, and any subset.

Detail

Change where a revision table sits, which way its rows stack, or its rows - absolute values only, and any subset. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. rows replaces the whole list when sent - to add a revision, send every row plus the new one - and an empty list clears the block. Undoable, and it changes no geometry.

drawing.set_sheet

Change a sheet's size, orientation, scale or place in its drawing - absolute values only, and any subset.

Detail

Change a sheet's size, orientation, scale or place in its drawing - absolute values only, and any subset. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. size names a query.sheet_sizes row and width with height give a size it does not list - one or the other, never both. orientation on its own turns the sheet, swapping the two lengths without restating them. position is 1-based within this sheet's own drawing and is how sheets are reordered. A new size moves the title block and every table with the corner it sits nearest, so one placed 10 mm in from a corner is still 10 mm in from it; views stay where they are. The reply's offSheet names every block and view that no longer fits the page - empty when everything does. Undoable, and it changes no geometry - a sheet is a page, not a shape.

drawing.set_title_block

Change where a title block sits or its stored words - absolute values only, and any subset.

Detail

Change where a title block sits or its stored words - absolute values only, and any subset. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. A word sent as the empty string is cleared. The derived cells cannot be set here: change the document's record with doc.set_metadata, the sheet with drawing.set_sheet, the latest rev with the sheet's revision table, and the block follows. Undoable, and it changes no geometry.

drawing.set_view kernel

Change which bodies a view draws, which way it looks, where it sits on the page, its scale or whether hidden lines are drawn - absolute values only, and any subset.

Detail

Change which bodies a view draws, which way it looks, where it sits on the page, its scale or whether hidden lines are drawn - absolute values only, and any subset. A view made by drawing.project_view takes offset instead of x, y and direction, because it has one degree of freedom rather than three: it is aimed and aligned by the view it was projected from, and sending the wrong pair is refused rather than quietly stored. Absent fields are left exactly as they are, so a retry is always safe and nothing here is ever a nudge; send at least one. Sending scale as null puts the view back on its sheet's scale, which is how an inherited scale is restored once it has been overridden. broken shortens a long part: {axis, from, to, gap} takes the run between from and to out of the picture along that axis and draws the two ends gap apart with break lines between them, every dimension still stating the part's true length; null draws the view whole again. A break belongs to the view that owns the axis - a top view of a shaft broken along its length is broken by the front view's own band, because the two share the axis - so it is sent to the base view, or to a projected child only along the axis it does not share. breakout shows the inside of the part at one place without a second view - a local section: {x, y, radius, depth} cuts a round pocket into the picture, centred there in this view's own millimetres and depth deep behind the surface inside it, the floor hatched and its edge drawn thin; null fills it in again. radius and depth may be left out on a new break-out for a default read off the picture. A view is drawn with a break or a break-out, never both, and a detail of a broken-out view shows the pocket. Undoable, and it changes no geometry - a view is a picture, not a shape.

Import

Bringing other formats into a document, from CAD and print files to reference pictures.

import.3mf kernel

Read a 3MF package into this document as REFERENCE geometry - a mesh you can see, measure against and model over, and cannot edit.

Detail

Read a 3MF package into this document as REFERENCE geometry - a mesh you can see, measure against and model over, and cannot edit. It never becomes a body: a 3MF carries triangles rather than surfaces, and CoCAD does not pretend otherwise, so a reference mesh cannot be filleted, combined or exported as STEP. 3MF is what modern slicers and printers exchange, so this is how a print you have been sent comes in to be measured or modelled around. Send path for a file on disk, or content for base64 3MF bytes - exactly one of the two. Every object placed in the file's build arrives as one reference mesh, laid out where the file puts it, so a plate of six parts keeps its arrangement. Unlike STL and OBJ a 3MF states its own unit, and CoCAD honours it, so the size is right without being told - scale is there only to correct a file whose declared unit is wrong.

import.dxf dxf

Read a DXF drawing into this document as a new sketch.

Detail

Read a DXF drawing into this document as a new sketch. DXF is what laser cutters, waterjets, plotters and every 2D CAD package exchange, so this is how a profile somebody drew elsewhere becomes geometry you can extrude. Send path for a file on disk, or content for base64 DXF bytes - exactly one of the two - plus the plane, face or construction plane the drawing lands on. Lines, arcs, circles, ellipses, splines, points and polylines become sketch curves in the drawing's own coordinates; blocks are exploded; text, hatches and dimensions are annotation and are reported in skipped rather than imported. The drawing's declared unit is honoured, so an inch drawing arrives at the right size. The sketch and its curves arrive as one undoable step.

import.idf kernel

Read an IDF 3.0 circuit board into this document - the free text format every ECAD program (KiCad, Altium, Eagle, OrCAD) writes as a pair: the .emn board file (outline, drilled holes, where each component is placed) and the .emp library (each component's outline and height).

Detail

Read an IDF 3.0 circuit board into this document - the free text format every ECAD program (KiCad, Altium, Eagle, OrCAD) writes as a pair: the .emn board file (outline, drilled holes, where each component is placed) and the .emp library (each component's outline and height). The board becomes one body, cut by its holes and cutouts, and every placed component becomes a body of its own - its library outline, turned and placed, as tall as the library says, on the side it is placed on (named by its reference designator). All of them arrive under ONE feature as one undoable step, so query.board_layout { board } then finds the components without being told. A component that cannot be built is listed in skipped with why (unplaced, noLibrary, noLibraryEntry, noHeight, badOutline) rather than guessed at. Lengths are converted from the file's MM or THOU. Sections a case does not need (keepouts, notes, other outlines) are named in ignoredSections. Send path or content for the board, exactly one; the library is found beside a path, or sent with library or libraryContent.

import.iges kernel

Read an IGES file into this document as bodies.

Detail

Read an IGES file into this document as bodies. IGES is the older exchange format and is still what a lot of legacy tooling emits. Send path for a file on disk, or content for base64 IGES bytes - exactly one of the two. Every solid in the file becomes a body, in the file's own order; the bodies join the document you already have rather than replacing it, and arrive as one undoable step. The geometry is stored in the document, so saving and reopening does not need the original file. Expect to need heal more often than with STEP: most tools that write IGES write loose surfaces rather than solids, and healing is what sews them back into one.

import.jpeg

Read a JPEG image onto a plane as a CANVAS - a calibrated picture to trace over, which is how a broken part gets rebuilt from a photograph; .jpg and .jpeg are both JPEG.

Detail

Read a JPEG image onto a plane as a CANVAS - a calibrated picture to trace over, which is how a broken part gets rebuilt from a photograph; .jpg and .jpeg are both JPEG. The image lies on the support you name, at mmPerPixel millimetres per pixel; absent, CoCAD derives the calibration from the density the file states (a flatbed scan calibrates itself) and otherwise assumes 1, and the reply's calibration field says which happened. A canvas never becomes geometry: sketch over it on the same plane and build from the sketch. Send path for a file on disk, or content for base64 JPEG bytes - exactly one of the two. Send preview true first to see the size before anything lands. A sideways phone photo imports sideways - EXIF orientation is deliberately ignored everywhere - and rotation is the remedy.

import.obj kernel

Read a Wavefront OBJ file into this document as REFERENCE geometry - a mesh you can see, measure against and model over, and cannot edit.

Detail

Read a Wavefront OBJ file into this document as REFERENCE geometry - a mesh you can see, measure against and model over, and cannot edit. It never becomes a body: an OBJ carries triangles rather than surfaces, and CoCAD does not pretend otherwise, so a reference mesh cannot be filleted, combined or exported as STEP. OBJ is what most 3D software and most asset libraries write, so this is how a downloaded part or a model from another tool comes in to be worked around. Send path for a file on disk, or content for base64 OBJ bytes - exactly one of the two. The whole file arrives as ONE reference mesh: an OBJ's g groups are face-set labels rather than parts, so they are not split out. Materials, colours and texture coordinates are not read. An OBJ records no unit anywhere, so send scale to say what the numbers mean - and send preview true first to see the size before you decide.

import.png

Read a PNG image onto a plane as a CANVAS - a calibrated picture to trace over, which is how a broken part gets rebuilt from a photograph.

Detail

Read a PNG image onto a plane as a CANVAS - a calibrated picture to trace over, which is how a broken part gets rebuilt from a photograph. The image lies on the support you name, at mmPerPixel millimetres per pixel; absent, CoCAD derives the calibration from the density the file states (a flatbed scan calibrates itself) and otherwise assumes 1, and the reply's calibration field says which happened. A canvas never becomes geometry: sketch over it on the same plane and build from the sketch. Send path for a file on disk, or content for base64 PNG bytes - exactly one of the two. Send preview true first to see the size before anything lands.

import.step kernel

Read a STEP file into this document as bodies.

Detail

Read a STEP file into this document as bodies. STEP is the exchange format every CAD, CAM and inspection package writes, so this is how a part enters CoCAD. Send path for a file on disk, or content for base64 STEP bytes - exactly one of the two. Every solid in the file becomes a body, in the file's own order; the bodies join the document you already have rather than replacing it, and arrive as one undoable step. The geometry is stored in the document, so saving and reopening does not need the original file.

import.stl kernel

Read an STL file into this document as REFERENCE geometry - a mesh you can see, measure against and model over, and cannot edit.

Detail

Read an STL file into this document as REFERENCE geometry - a mesh you can see, measure against and model over, and cannot edit. It never becomes a body: an STL carries triangles rather than surfaces, and CoCAD does not pretend otherwise, so a reference mesh cannot be filleted, combined or exported as STEP. This is how a 3D scan, a downloaded part or a mesh from another tool comes in to be worked around. Send path for a file on disk, or content for base64 STL bytes - exactly one of the two; both encodings are read and neither has to be named. An STL records no unit anywhere, so send scale to say what the numbers mean - and send preview true first to see the size before you decide. A facet with two corners in one place cannot be drawn and is left out as the file is read; the reply's skippedFacets says how many, so its triangle count and the file's own facet count always add up.

Export

Writing a document out to other formats. Commands marked CoCAD Pro only need a License File.

export.3mf kernel

Write bodies to a 3MF file - the modern 3D-printing format, and what slicers and print services increasingly ask for in place of STL.

Detail

Write bodies to a 3MF file - the modern 3D-printing format, and what slicers and print services increasingly ask for in place of STL. Like STL and OBJ this writes triangles rather than exact surfaces, so tolerance is how closely they follow the model. What 3MF adds is that the file says what its numbers MEAN: the unit is written into it, so a 30 mm bracket arrives 30 mm instead of depending on what the reader assumes. Each body arrives as its own named object a consumer can select, hide and print separately, so the names you gave them and the boundaries between them both survive. Every object is checked to be a closed, correctly-oriented mesh before it is written, and a body that is not one is refused rather than written - a bad mesh's next reader is somebody's printer. Each body's colour - its own appearance, else its material's look - is written as a base material named for its material (or Colour 1, Colour 2 for paint alone), so a multi-material printer's slicer opens the plate with filaments already assigned; bodies sharing a material and colour share one entry. The reply's materials lists what was written with the colour the file holds, and noMaterialBodyIds names the bodies written with none - a body with no colour anywhere, which doc.set_appearance fixes. Face and placement colours are not written. Writes every body in the document unless bodies names a subset - hidden ones included, because hiding a body is a way of looking at the document rather than a change to it. The model is written as modelled, Z up, which is the format's own convention. The reply says how many triangles were written, and carries the same watertight and notWatertightBodyIds fields the other mesh exports do - but on this format they are always true and empty on success, because 3MF refuses a body without a closed surface where STL, OBJ and glTF write it with a warning. A mesh body - one made from a scan - is written as the triangles it holds, and tolerance does not apply to it; its triangles must close up into one consistently wound surface, or it is refused for the same reason. Exporting changes nothing and cannot be undone; the file is written atomically, and the reply says where the bytes landed. Set preview true to be told how many triangles and how many bytes it would be, without writing anything. Send slice to have a slicer installed here (PrusaSlicer, Bambu Studio or OrcaSlicer, chosen from query.open_with) slice the written file with profiles exported from it, into G-code or a sliced 3MF a printer prints; the reply's slice says whether it worked. Add send to slice to then send the sliced file to a printer query.printers lists and, if you say so, start it.

export.build_instructions kernel

CoCAD Pro only.

Detail

CoCAD Pro only. Write the model's build instructions: a multi-page A4 PDF that shows how the part is made, step by step. The first page is the finished part with its parts list (every visible body, its name and material); then one page per step of the timeline that made geometry - "Step 3 of 7: Extrude 1" - showing the model REBUILT to that step, with the faces that step made drawn in amber over a thin drawing of the rest, captioned with the feature's intent note when it has one (feature.set_intent). Undone steps are left out; sketches, construction planes, parameters and notes make no geometry and get no page; a step that made no face of its own (a move, say) is listed in skipped with the reason. Every step page shares one scale so the part grows on the paper. The pictures are hidden-line drawings, so a mesh, subdiv or field body is not drawn and is named in undrawn. Name an explode state (explode) to end the booklet with the finished part drawn pulled apart. At most 100 steps; each is one rebuild, so a long timeline takes a while. Exporting changes nothing and cannot be undone; the file is written atomically. Set preview true to rebuild and draw everything without writing, and open true to open the PDF once written.

export.dxf not the fixture

CoCAD Pro only.

Detail

CoCAD Pro only. Write one sketch, or one flat face of a solid, to a DXF file - the format laser cutters, waterjets, plotters, CNC routers and every 2D CAD package read, so this is how a profile you drew in CoCAD gets cut. Lines, arcs, circles, ellipses, splines and points are written exactly, with no tolerance and nothing sampled. The drawing is the sketch's - or the face's - OWN plane seen flat, never world space, because a 2D tool is the point of this format: a sketch on an inclined face arrives as an ordinary flat drawing. Millimetres are declared in the file, so the receiving program knows what the numbers mean. Construction geometry goes on a CONSTRUCTION layer and centrelines on CENTERLINE, with everything else on layer 0, so a cutter can leave the guides out - and import.dxf reads those same layers back. What a DXF cannot hold is not written: dimensions, constraints and the link a projected curve keeps to the edge it came from all stay in CoCAD. Exporting changes nothing and cannot be undone; the file is written atomically, and the reply says where the bytes landed. Set preview true to be told how big the drawing would be, and how big each part on a sheet came out, without writing anything. A face is exported as its own boundary and holes: exactly the drawing you would get by sketching on that face and projecting it, so the two agree curve for curve. Set kerf to your cutter's width and what comes out is the CUTTING PATH instead - every loop moved half a kerf away from the material - so the part comes off the machine the size it is in CoCAD.

export.flat_pattern kernel

CoCAD Pro only.

Detail

CoCAD Pro only. Write one sheet-metal part's flat pattern to a DXF file - the blank it is cut from, ready for a laser, a waterjet or a turret punch, with the bend lines the brake operator needs on their own layers. The outline and every hole go on layer 0, exactly where export.dxf puts a flat face, so a cutter reads a blank the way it already reads a part. Each bend line runs down the MIDDLE of the band of flat that bend eats, on layer BEND_UP when the metal folds towards the side the blank is seen from and BEND_DOWN when it folds away - which is the one fact a DXF has nowhere else to keep, so it is kept in the layer name. Only the layers actually used are declared, so a part with no bends offers no bend layer. Lines, arcs, circles, ellipses and splines are written exactly, with no tolerance and nothing sampled; millimetres are declared in the file, and the blank's minimum corner sits at the origin so width and height in the reply are the piece of stock it needs. Nothing is unfolded and nothing is stored: the layout is derived from the part every time you ask, so the file and the model can never disagree. The part must carry a sheet-metal rule, because how much flat a bend eats depends on where the neutral axis sits inside the metal - set one with feature.base_flange or doc.set_sheet_metal_rule. Use query.flat_pattern for the same layout as numbers, and query.bends for the bend table that goes beside it. Exporting changes nothing and cannot be undone; the file is written atomically and the reply says where the bytes landed and what was drawn. Set preview true to be told how big the file would be and what it would hold without writing anything.

export.gltf kernel

Write bodies to a binary glTF file (.glb) - the format the viewer ecosystem reads, from web viewers and game engines to Windows' own 3D Viewer, so this is how a part gets LOOKED at rather than machined.

Detail

Write bodies to a binary glTF file (.glb) - the format the viewer ecosystem reads, from web viewers and game engines to Windows' own 3D Viewer, so this is how a part gets LOOKED at rather than machined. Like STL, OBJ and 3MF this writes triangles rather than exact surfaces, so tolerance is how closely they follow the model. Each body arrives as its own named node, so the names you gave them and the boundaries between them both survive. Writes every body in the document unless bodies names a subset - hidden ones included, because hiding a body is a way of looking at the document rather than a change to it. The one thing this format does differently from every other export: glTF's specification requires Y up and metres, so the model is TURNED and SCALED on the way out - a 30 mm bracket modelled Z up arrives as 0.03 along Y, which is the file being correct rather than wrong. Colours and materials are not written, because nothing in CoCAD gives a body a colour yet. Only the binary .glb encoding is written; the .gltf-plus-.bin pair is two files and this writes one. The reply says how many triangles were written, and whether every exported body is watertight - notWatertightBodyIds names any body without a closed surface, most often because two lumps meet along a single edge or corner instead of merging. It is a warning rather than a refusal, and matters less here than for a printing format: a viewer will show such a body quite happily. A mesh body - one made from a scan - is written as the triangles it holds, with no normals so a viewer shades it flat, and tolerance does not apply to it. Exporting changes nothing and cannot be undone; the file is written atomically, and the reply says where the bytes landed. Set preview true to be told how many triangles and how many bytes it would be, and whether it is watertight, without writing anything.

export.iges kernel

CoCAD Pro only.

Detail

CoCAD Pro only. Write bodies to an IGES file. IGES is the older exchange format, and it is what some CAM, moldmaking and inspection tools still ask for; send STEP unless a consumer names IGES. Writes every body in the document unless bodies names a subset - hidden ones included, because hiding a body is a way of looking at the document rather than a change to it. Bodies are written as solids, not as loose surfaces. Note that IGES has no place to put a body's name, so the names you gave them do not survive the trip - export STEP if the consumer needs them. Exporting changes nothing and cannot be undone; the file is written atomically, and the reply says where the bytes landed.

export.lithophane not the fixture

Write a canvas's picture as a lithophane - a thin plate that shows the picture when light shines through it - to a binary STL file ready to slice and print.

Detail

Write a canvas's picture as a lithophane - a thin plate that shows the picture when light shines through it - to a binary STL file ready to slice and print. Where the picture is dark the plate is thick, where it is bright the plate is thin, between minThickness and maxThickness. A flat plate lies with its back on the build plate and the relief facing up, reading the right way round from above, centred on the origin; print it standing up for the finest detail. A cylinder (shape) is the same plate rolled into a lamp shade or a curved panel, standing on the build plate; a dome is the picture's inscribed circle on a hollow spherical cap, standing on its rim. The picture is read as the canvas's file holds it, before any rotation or flip the canvas has in the model, and transparent areas count as white. Nothing is added to the document and it cannot be undone; the file is written atomically, and the reply says where the bytes landed. Set preview true to be told the size of the plate and the file without writing anything.

export.obj kernel

Write bodies to a Wavefront OBJ file - the mesh format renderers, game engines and sculpting tools read.

Detail

Write bodies to a Wavefront OBJ file - the mesh format renderers, game engines and sculpting tools read. Like STL this writes triangles rather than exact surfaces, so tolerance is how closely they follow the model; unlike STL, each body arrives as its own named group, so the names you gave them and the boundaries between them both survive. Writes every body in the document unless bodies names a subset - hidden ones included, because hiding a body is a way of looking at the document rather than a change to it. The model is written as modelled, Z up. Like STL, an OBJ carries bare numbers and does not say what unit they are in - export 3MF if a consumer needs that stated in the file. The reply says how many triangles were written, and whether every exported body is watertight - notWatertightBodyIds names any body without a closed surface, most often because two lumps meet along a single edge or corner instead of merging. It is a warning rather than a refusal, and the fix is in the model rather than in the export. A mesh body - one made from a scan - is written as the triangles it holds, and tolerance does not apply to it. Exporting changes nothing and cannot be undone; the file is written atomically, and the reply says where the bytes landed. Set preview true to be told how many triangles and how many bytes it would be, and whether it is watertight, without writing anything.

export.quote kernel

CoCAD Pro only.

Detail

CoCAD Pro only. Write one body's quote packet: a one-page A4 PDF with pictures of the part (isometric, front and top at one scale, plus right for a print or the flat blank for a sheet-metal part), what it is made of, its volume and mass, and how long it takes and what it costs. Give print to quote a filament 3D print - its contents are exactly query.print_estimate's arguments (printer profile, buildDirection, rates) - or sheetMetal to quote a folded part - exactly query.flat_pattern's rates; exactly one. Every figure on the page is that read's own answer, and the volume and mass are query.mass_properties' (the mass needs a material set with doc.set_material), so the packet cannot disagree with the reads; the reply carries the read's whole answer as estimate. A read's refusal is this command's, in its words. Without rates the page says so and prices nothing. It is an ESTIMATE, and the page says what it does not count; no margin or tax is added. A mesh body (a scan) can be quoted as a print, with no pictures - it has no edges to draw. Exporting changes nothing and cannot be undone; the file is written atomically. Set preview true to read every figure without writing anything, and open true to open the PDF once written.

export.recipe

CoCAD Pro only.

Detail

CoCAD Pro only. Write an ordered list of commands to a recipe file - the plan an AI proposed and you accepted, or with source: "document" the whole history of the open document - kept as something you can name, file and send to somebody. Pass exactly one of steps and source. Every step is checked against this core's own registry first: an unknown command, an argument its schema refuses, a step that only reads, or one that acts on the running core rather than on the model is refused whole, naming the step by index, so a recipe on disk is always a plan this build could actually run. A whole document is also replayed as plain commands first and refused, naming the step, if that would not rebuild the document you have - a reordered or suppressed history keeps numbering a recipe cannot carry. With steps it needs no open document; it changes nothing and cannot be undone; read path back from the reply for where the bytes landed.

export.slices kernel

CoCAD Pro only.

Detail

CoCAD Pro only. Slice a solid into flat parts for sheet stock and write every part to ONE DXF sheet - the slice-for-assembly route: cut the parts from plywood, acrylic or card on a laser (or by hand) and the part is rebuilt at full size. mode stack cuts parallel layers, each thickness thick, along direction (+Z by default, bottom-up), to glue face to face in order. There are ceil(height / thickness) layers starting flush with the part's low face, so the stack is never short; when the height is not a whole number of sheets the last sheet stands proud and overhang says by how much. Each layer is the cross-section at the middle of the material it stands for, holes and separate pieces included, drawn exactly (lines, arcs, circles, splines - nothing sampled) and seen from the direction's positive end so no outline is mirrored. Every layer is on its own DXF layer named SLICE_001, SLICE_002 and so on in stack order. mode hash cuts upright sheets instead, in two families square to the two axes across direction (which is then UP; +Z by default makes family A square to X and family B square to Y), pitch apart and centred on the part. Where an A sheet crosses a B sheet each gives up half of the material they share: A is slotted from its top down to the middle, B from its bottom up, each slot thickness plus clearance wide, so the B sheets drop onto the A sheets and the grid holds itself together with no glue. Every sheet is drawn with up at the top of the page, on its own DXF layer SLICE_A001 upward or SLICE_B001 upward along its own axis. mode plates reads the part as the OUTSIDE of a box: every flat face (flat neighbours in one plane are one face) becomes a plate one sheet thick lying just inside it, and where two plates meet square - an outside corner or an inside one - the edge is cut into an odd number of fingers about finger long (twice the thickness by default) that interleave, the lower-numbered plate taking both ends, so the plates press together into a hollow copy of the part. A curved face (a fillet, a bore) gets no plate and is listed in openFaces; two plates meeting at any angle but square are refused by name, and so are two walls closer than two sheets. Every plate is drawn seen from outside with direction up the page, on its own DXF layer PLATE_001 upward in the body's face order, and the reply's joints lists every jointed edge with its two plates and its finger count. In every mode the parts sit in a grid on the sheet, the first at the origin, each in a cell the size of the largest plus spacing, and the reply lists every part: its number, its DXF layer, its size and corner on the sheet, how many separate pieces it is, and its area - for stack and hash where it was cut (at, a world coordinate along its own axis), for hash its family, its axis and how many slots it has, and for plates the faces it stands behind, its outward normal and how many joints it has. A part the plane finds no material in is listed with pieces 0 and keeps its cell. Only an exact solid slices - a sheet or a curve has nothing to cut, and a scan (mesh body) is not sliced yet. More than 500 parts is refused: that is a units mistake. Exporting changes nothing and cannot be undone; the file is written atomically and the reply says where the bytes landed. Set preview true to see the plan without writing anything.

export.step kernel

CoCAD Pro only.

Detail

CoCAD Pro only. Write bodies to a STEP file. STEP is the exchange format every CAD, CAM and inspection package reads, so this is how a part leaves CoCAD. Writes every body in the document unless bodies names a subset - hidden ones included, because hiding a body is a way of looking at the document rather than a change to it. Each body arrives under the name you gave it. Exporting changes nothing and cannot be undone; the file is written atomically, and the reply says where the bytes landed.

export.stl kernel

Write bodies to an STL file - the format 3D printers, slicers and mesh tools read.

Detail

Write bodies to an STL file - the format 3D printers, slicers and mesh tools read. Unlike STEP and IGES this writes triangles rather than exact surfaces, so tolerance is how closely they follow the model. Writes every body in the document unless bodies names a subset - hidden ones included, because hiding a body is a way of looking at the document rather than a change to it. Note that STL holds nothing but triangles: body names and the boundaries between separate bodies do not survive, so a two-body part arrives as one mesh - export OBJ if the consumer needs either. Nor does an STL say what its numbers mean, so whether a 30 mm part arrives 30 mm is up to the reader's assumed unit - export 3MF if that matters, which for a slicer it usually does. The reply says how many triangles were written, and whether every exported body is watertight - a printer or slicer needs a closed surface, and notWatertightBodyIds names any body that has not got one, most often because two lumps meet along a single edge or corner instead of merging. It is a warning rather than a refusal: that is a shape you can model on purpose, and the fix is in the model rather than in the export. A mesh body - one made from a scan - is written as the triangles it holds, and tolerance does not apply to it. Exporting changes nothing and cannot be undone; the file is written atomically, and the reply says where the bytes landed. Set preview true to be told how many triangles and how many bytes it would be, and whether it is watertight, without writing anything.

export.svg not the fixture

CoCAD Pro only.

Detail

CoCAD Pro only. Write one sketch, or one flat face of a solid, to an SVG file - the drawing format every browser, vinyl cutter, laser cutter, plotter and illustration program reads, so this is how a profile you drew in CoCAD gets cut, printed or put on a page. Lines, arcs, circles, ellipses, points and splines up to cubic are written exactly, with no tolerance and nothing sampled; a spline of degree four or more, or one whose control points carry weights, is refused rather than smoothed, and the message names the curve and points at export.dxf, which holds it exactly. The drawing is the sketch's - or the face's - OWN plane seen flat, never world space. Millimetres are declared in the root element, so one SVG unit is one millimetre and the file opens at real size. SVG measures y downwards where CoCAD measures it up, so the whole drawing is flipped once on the way out and arrives the right way round rather than mirrored. Construction geometry and centrelines go in their own groups, so a cutter can leave the guides out. What an SVG cannot hold is not written: dimensions, constraints and the link a projected curve keeps to the edge it came from all stay in CoCAD. Exporting changes nothing and cannot be undone; the file is written atomically, and the reply says where the bytes landed. Set preview true to be told how big the drawing would be, and how big each part on a sheet came out, without writing anything - and to find out whether this format can hold the drawing before choosing a file name. A face is exported as its own boundary and holes: exactly the drawing you would get by sketching on that face and projecting it, so the two agree curve for curve. Set kerf to your cutter's width and what comes out is the CUTTING PATH instead - every loop moved half a kerf away from the material - so the part comes off the machine the size it is in CoCAD.

export.video not the fixture

CoCAD Pro only.

Detail

CoCAD Pro only. Write a video of the model as a looping animated GIF, which plays in any browser, chat or slide deck. kind turntable (the default) takes the camera once round the part: every frame is a screenshot through your own camera (point it with view.set_camera first; type fit frames the whole model) with only its bearing turned, drawn by the same render provider view.screenshot uses, so the video looks exactly like the window; explode and section draw every frame pulled apart or cut open. kind replay plays the timeline back - one frame per step that made a feature or a body, each the model rebuilt to that step and drawn through your camera unturned, so the part builds itself, resting on the finished part at the end; it is drawn by a cocad-render worker (CoCAD starts one when none is connected) and holds at most 100 steps. A GIF holds at most 256 colours, so smooth shading bands a little. The frames are drawn one after another - sixty take about as long as sixty screenshots - and nothing is written if any of them fails. Exporting changes nothing and cannot be undone; the file is written atomically. Set preview true to draw and encode without writing, and open true to open the GIF once written.

export.viewer kernel

Write the model as ONE web page anyone can open in a browser and turn round - drag to turn, right-drag to move, scroll or pinch to zoom - with no CoCAD, no install, no account and no internet: the page loads nothing from anywhere, so it works offline, from a USB stick or attached to an email.

Detail

Write the model as ONE web page anyone can open in a browser and turn round - drag to turn, right-drag to move, scroll or pinch to zoom - with no CoCAD, no install, no account and no internet: the page loads nothing from anywhere, so it works offline, from a USB stick or attached to an email. It is how a part is SHOWN to somebody. Each body is drawn exactly as CoCAD's own window draws it - the same triangles query.tessellate answers and the same edges query.edges answers, at the body's own display density - in its colour (its appearance, else its material's look), and listed by name so the viewer can show or hide it; a hidden body is in the page, hidden. Scans, freeform and field bodies are drawn too. Every page says Made with CoCAD. Writes every body unless bodies names a subset. The page is for looking at: its numbers are single precision and it is not an exchange format - send STEP to somebody who will machine the part. Exporting changes nothing and cannot be undone; the file is written atomically. Set preview true to be told how many triangles, edges and bytes it would be without writing anything, and open true to open the page in this computer's browser once written.