Repository navigation
smlibpy 0.3.0
Kernel tools that SMLib has and smlibpy did not offer yet: USD files with the exact bodies, rays and selecting by a ray, surfaces fitted to point clouds, Booleans of any mesh, parts made of cells, curve tools and blends between surfaces. All of them are in smlibwasm too, with the same tests. And the MCP's live view is now Buerligons, the ClassCAD app.
New
Buerligons as the live view. The MCP server shows the session in Buerligons, served on 127.0.0.1 in view mode: you turn the model, select and measure faces and edges, and save it as STEP, STL, glTF, OBJ, USD or SMLib's format. What you select reaches the agent: get_selection gives each face, edge or vertex with its measurements and the expression that reaches it in a script (plate.faces()[6]), so "fillet the edge I selected" works; set_selection highlights what the agent means. A selection lasts until the model changes. The app comes from the npm package @classcad/mcp at a pinned version and hash, downloaded on first use and cached; smlibpy's own three.js viewer page is gone.
USD. export_usd writes each body as a BrepArray prim, the B-rep of NVIDIA's usd-brep (its omniSolid schema), with its exact surfaces and curves, its name and its color; usd-brep, its usdview plugin and Omniverse read them as solids. mesh=True adds a Mesh prim per body for viewers that only draw meshes. import_usd reads the bodies back, also files from usd-brep. The conversion is usd-brep's own, compiled in without OpenUSD; files are text (.usda), and usdcat converts them to .usdc or .usdz. The tests check the files with NVIDIA's validator and OpenUSD. export, load and the MCP's save and load take .usda too.
export_usd([bracket, cover], "assembly.usda")
parts = import_usd("assembly.usda")Rays. raycast(origin, direction) on parts, sheets, faces and meshes gives the exact points where a ray meets them, nearest first, with the distance, the face and the outward normal at each.
part = Box(40, 30, 20) - Cylinder(5, 30)
[h.distance for h in part.raycast((-50, 0, 0), (1, 0, 0))] # [30.0, 45.0, 55.0, 70.0]Selecting by a ray. faces().hit_by(origin, direction) selects the faces a ray meets, nearest first, and chains with the other selectors: part.faces().hit_by(...).first is what the ray sees first. On a list of parts it picks the parts the ray meets.
Surfaces through point clouds. surface(points) with points in any order (a scan) fits a surface to them: 2,000 points in 3 ms, 20,000 in 30 ms. controls= and smoothing= set how closely it follows them; for noisy points, more smoothing or fewer control points make it follow the shape, not the noise. Its normal points up.
Mesh Booleans on any mesh. +, - and & of closed meshes from STL files, Mesh(...) and tessellate now give closed meshes: the polygons with holes that the kernel leaves are triangulated, and the normals come from the triangles.
Parts of cells. merge(a, b) makes one part in which overlaps become cells of their own and touching cells share their faces, as for models of several materials. cells() gives each cell as a solid. USD keeps the cells together; STEP writes one solid per cell.
Curve tools. edge.nurbs() gives the degree, knots, control points and weights of any edge; make_compatible(a, b, ...) turns curves into B-splines of one degree and one knot vector; edge.remove_knots() takes out the knots a curve does not need.
Blends between surfaces. surface_fillet(a, b, radius, sides=(1, 1)) rounds between two sheets that are no part of one body, such as two crossing pipes, and returns the blend as a sheet.
The skill has a tested guide for each, the MCP finds them by plain words, and the docs and the feature sheet on the website show them.