Every part below was built with the blacksmith and written out by it. The code on the left is the whole program, in the language of your choice; the files on the right are what it wrote, to open in your own CAD or in the viewer. The STEP is the kernel's own, exact; the meshes are the reader's tessellation of it at its default tolerance.
from cadaclysm_blacksmith import Axis, Profile, Selector, Workplane
plate = Workplane.xy().extrude(Profile.rect(120, 80), 14).solid()
boss = (Workplane.from_solid(plate)
.faces(Selector.max(Axis.Z)).workplane()
.extrude(Profile.circle(22), 26).solid())
part = plate.join(boss)
bore = Workplane.xy().extrude(Profile.circle(11), 60).solid().translate(0, 0, -10)
part = part.cut(bore)
# The plate's four vertical corners: the lines along Z between two planes# (the boss has vertical seams too, but those lie on its cylinder).
corners = [e for e in part.edges
if e.is_line andabs(e.direction[2]) > 0.99andall(part.face_kind(f) == "plane"for f in e.faces)]
part = part.fillet(corners, 12)
part.step("plate.stp")
using Cadaclysm.Blacksmith;
usingvar plate = Workplane.Xy().Extrude(Profile.Rect(120, 80), 14).Solid();
usingvar boss = Workplane.FromSolid(plate)
.Faces(Selector.Max(Axis.Z)).OnFace()
.Extrude(Profile.Circle(22), 26).Solid();
usingvar joined = plate.Join(boss);
usingvar bore = Workplane.Xy().Extrude(Profile.Circle(11), 60).Solid().Translate(0, 0, -10);
usingvar bored = joined.Cut(bore);
// The plate's four vertical corners: the lines along Z between two planes// (the boss has vertical seams too, but those lie on its cylinder).var corners = bored.Edges.Where(e => e.IsLine && Math.Abs(e.Direction![2]) > 0.99
&& e.Faces.All(f => bored.FaceKind(f) == "plane"));
usingvar part = bored.Fillet(corners, 12);
part.Step("plate.stp");
package main
import (
"log""math""github.com/rdeioris/cadaclysm-sdk/go/blacksmith"
)
func must[T any](v T, err error) T {
if err != nil {
log.Fatal(err)
}
return v
}
funcmain() {
plate := must(blacksmith.XY().Extrude(must(blacksmith.Rect(120, 80)), 14).Solid())
defer plate.Close()
boss := must(blacksmith.FromSolid(plate).
Faces(blacksmith.Max(blacksmith.AxisZ)).OnFace().
Extrude(must(blacksmith.Circle(22)), 26).Solid())
defer boss.Close()
joined := must(plate.Join(boss, blacksmith.DefaultTolerance))
defer joined.Close()
bore := must(must(blacksmith.XY().Extrude(must(blacksmith.Circle(11)), 60).Solid()).Translate(0, 0, -10))
defer bore.Close()
bored := must(joined.Cut(bore, blacksmith.DefaultTolerance))
defer bored.Close()
// The plate's four vertical corners: the lines along Z between two planes// (the boss has vertical seams too, but those lie on its cylinder).var corners []intfor _, e := rangemust(bored.Edges()) {
d, ok := e.Direction()
if !ok || math.Abs(d[2]) <= 0.99 {
continue
}
planes := truefor _, f := range e.Faces {
planes = planes && must(bored.FaceKind(f)) == "plane"
}
if planes {
corners = append(corners, e.Index)
}
}
part := must(bored.Fillet(corners, 12, blacksmith.FilletTolerance))
defer part.Close()
if err := part.Step("plate.stp", "", "mm"); err != nil {
log.Fatal(err)
}
}
import java.util.Arrays;
publicclass Plate {
publicstaticvoidmain(String[] args) {
try (var plate = Blacksmith.Workplane.xy().extrude(Blacksmith.Profile.rect(120, 80), 14).solid();
var boss = Blacksmith.Workplane.fromSolid(plate)
.faces(Blacksmith.Selector.max(Blacksmith.Axis.Z)).onFace()
.extrude(Blacksmith.Profile.circle(22), 26).solid();
var joined = plate.join(boss);
var bore = Blacksmith.Workplane.xy().extrude(Blacksmith.Profile.circle(11), 60).solid().translate(0, 0, -10);
var bored = joined.cut(bore)) {
// The plate's four vertical corners: the lines along Z between two planes// (the boss has vertical seams too, but those lie on its cylinder).var corners = bored.edges().stream()
.filter(e -> e.isLine() && Math.abs(e.direction()[2]) > 0.99)
.filter(e -> Arrays.stream(e.faces()).allMatch(f -> bored.faceKind(f).equals("plane")))
.toList();
try (var part = bored.fillet(corners, 12)) {
part.step("plate.stp");
}
}
}
}
const { Axis, Profile, Selector, Workplane } = require('cadaclysm/blacksmith');
const plate = Workplane.xy().extrude(Profile.rect(120, 80), 14).solid();
const boss = Workplane.fromSolid(plate)
.faces(Selector.max(Axis.Z)).workplane()
.extrude(Profile.circle(22), 26).solid();
let part = plate.join(boss);
const bore = Workplane.xy().extrude(Profile.circle(11), 60).solid().translate(0, 0, -10);
part = part.cut(bore);
// The plate's four vertical corners: the lines along Z between two planes// (the boss has vertical seams too, but those lie on its cylinder).const corners = part.edges().filter((e) => e.isLine && Math.abs(e.direction[2]) > 0.99
&& e.faces.every((f) => part.faceKind(f) === 'plane'));
part = part.fillet(corners, 12);
part.step('plate.stp');
use cadaclysm_sdk::blacksmith::{Axis, Profile, Selector, Unit, Workplane, DEFAULT_TOLERANCE, FILLET_TOLERANCE};
fnmain() -> cadaclysm_sdk::Result<()> {
let plate = Workplane::xy().extrude(&Profile::rect(120.0, 80.0)?, 14.0)?.solid()?;
let boss = Workplane::from_solid(&plate)
.faces(&Selector::Max(Axis::Z))?
.on_face()?
.extrude(&Profile::circle(22.0)?, 26.0)?
.solid()?;
let joined = plate.join(&boss, DEFAULT_TOLERANCE)?;
let bore = Workplane::xy().extrude(&Profile::circle(11.0)?, 60.0)?.solid()?.translate(0.0, 0.0, -10.0)?;
let bored = joined.cut(&bore, DEFAULT_TOLERANCE)?;
// The plate's four vertical corners: the lines along Z between two planes// (the boss has vertical seams too, but those lie on its cylinder).letmut corners = Vec::new();
for edge in bored.edges()? {
let vertical = edge.direction().is_some_and(|d| d[2].abs() > 0.99);
letmut planes = true;
for &face in &edge.faces {
planes = planes && bored.face_kind(face)? == "plane";
}
if vertical && planes {
corners.push(edge.index);
}
}
let part = bored.fillet(&corners, 12.0, FILLET_TOLERANCE)?;
part.step("plate.stp", None, Unit::Millimetre)
}
import Blacksmith
let plate = try Workplane.xy().extrude(Profile.rect(120, 80), 14).solid()
let boss = try Workplane.fromSolid(plate)
.faces(.max(.z)).workplane()
.extrude(Profile.circle(22), 26).solid()
var part = try plate.join(boss)
let bore = try Workplane.xy().extrude(Profile.circle(11), 60).solid().translate(0, 0, -10)
part = try part.cut(bore)
// The plate's four vertical corners: the lines along Z between two planes// (the boss has vertical seams too, but those lie on its cylinder).let corners = try part.edges.filter { e inguardlet d = e.direction, abs(d.z) > 0.99else { returnfalse }
returntry e.faces.allSatisfy { try part.faceKind($0) == "plane" }
}
part = try part.fillet(corners, 12)
try part.step("plate.stp")
local bs = require("cadaclysm_blacksmith")
local Axis, Profile, Selector, Workplane = bs.Axis, bs.Profile, bs.Selector, bs.Workplane
local plate = Workplane.xy():extrude(Profile.rect(120, 80), 14):solid()
local boss = Workplane.from_solid(plate)
:faces(Selector.max(Axis.Z)):workplane()
:extrude(Profile.circle(22), 26):solid()
local part = plate:join(boss)
local bore = Workplane.xy():extrude(Profile.circle(11), 60):solid():translate(0, 0, -10)
part = part:cut(bore)
-- The plate's four vertical corners: the lines along Z between two planes-- (the boss has vertical seams too, but those lie on its cylinder).localfunctionbetween_planes(edge)
for _, f inipairs(edge.faces) doif part:face_kind(f) ~= "plane"thenreturnfalseendendreturntrueendlocal corners = {}
for _, e inipairs(part.edges) doif e.is_line and math.abs(e.direction[3]) > 0.99andbetween_planes(e) then
corners[#corners + 1] = e
endend
part = part:fillet(corners, 12)
part:step("plate.stp")
Plate with a boss
Join, cut, fillet
A 120 × 80 × 14 plate, a boss joined on its top face, an 11 mm bore cut through both, the four vertical corners rounded at 12. Every face is a plane or a cylinder, the corner fillets included; the STEP says so.
use cadaclysm_sdk::blacksmith::{Solid, Unit, FILLET_TOLERANCE};
fnmain() -> cadaclysm_sdk::Result<()> {
let block = Solid::cuboid(20.0, 20.0, 20.0)?;
let edges: Vec<u32> = block.edges()?.iter().map(|e| e.index).collect();
let part = block.fillet(&edges, 2.0, FILLET_TOLERANCE)?;
part.step("box-fillet-all.stp", None, Unit::Millimetre)
}
import Blacksmith
let box = try Solid.cuboid(20, 20, 20)
let part = try box.fillet(box.edges, 2)
try part.step("box-fillet-all.stp")
local Solid = require("cadaclysm_blacksmith").Solid
local box = Solid.cuboid(20, 20, 20)
local part = box:fillet(box.edges, 2)
part:step("box-fillet-all.stp")
Rounded box
Fillet every edge
A 20 mm cube with its twelve edges rounded at 2 in one call, which is the whole of the program. The twelve bands are cylinders and the eight corners where three of them meet are patches of a sphere.
use cadaclysm_sdk::blacksmith::{Solid, Unit, FILLET_TOLERANCE};
fnmain() -> cadaclysm_sdk::Result<()> {
let block = Solid::cuboid(20.0, 20.0, 20.0)?;
let edges: Vec<u32> = block.edges()?.iter().map(|e| e.index).collect();
let part = block.chamfer(&edges, 2.0, FILLET_TOLERANCE)?;
part.step("box-chamfer-all.stp", None, Unit::Millimetre)
}
import Blacksmith
let box = try Solid.cuboid(20, 20, 20)
let part = try box.chamfer(box.edges, 2)
try part.step("box-chamfer-all.stp")
local Solid = require("cadaclysm_blacksmith").Solid
local box = Solid.cuboid(20, 20, 20)
local part = box:chamfer(box.edges, 2)
part:step("box-chamfer-all.stp")
Bevelled box
Chamfer every edge
The same cube with every edge cut back 2 along both its faces. Twelve bevels and eight triangular corners, twenty-six faces in all and every one of them a plane.
from cadaclysm_blacksmith import Profile, Solid, Workplane
plate = Solid.cuboid(60, 40, 4).translate(30, 20, 2)
# Six by four holes of radius 2.5, each a short cylinder cut through the plate.for i inrange(6):
for j inrange(4):
hole = Workplane.xy().extrude(Profile.circle(2.5), 6).solid()
plate = plate.cut(hole.translate(7 + 9.2 * i, 7 + 8.7 * j, -1))
plate.step("plate-holes.stp")
using Cadaclysm.Blacksmith;
var plate = Solid.Cuboid(60, 40, 4).Translate(30, 20, 2);
// Six by four holes of radius 2.5, each a short cylinder cut through the plate.for (var i = 0; i < 6; i++)
for (var j = 0; j < 4; j++)
{
usingvar hole = Workplane.Xy().Extrude(Profile.Circle(2.5), 6).Solid();
plate = plate.Cut(hole.Translate(7 + 9.2 * i, 7 + 8.7 * j, -1));
}
plate.Step("plate-holes.stp");
package main
import (
"log""github.com/rdeioris/cadaclysm-sdk/go/blacksmith"
)
func must[T any](v T, err error) T {
if err != nil {
log.Fatal(err)
}
return v
}
funcmain() {
plate := must(must(blacksmith.Cuboid(60, 40, 4)).Translate(30, 20, 2))
// Six by four holes of radius 2.5, each a short cylinder cut through the plate.for i := 0; i < 6; i++ {
for j := 0; j < 4; j++ {
hole := must(blacksmith.XY().Extrude(must(blacksmith.Circle(2.5)), 6).Solid())
moved := must(hole.Translate(7+9.2*float64(i), 7+8.7*float64(j), -1))
plate = must(plate.Cut(moved, blacksmith.DefaultTolerance))
hole.Close()
moved.Close()
}
}
if err := plate.Step("plate-holes.stp", "", "mm"); err != nil {
log.Fatal(err)
}
}
publicclass PlateHoles {
publicstaticvoidmain(String[] args) {
var plate = Blacksmith.Solid.cuboid(60, 40, 4).translate(30, 20, 2);
// Six by four holes of radius 2.5, each a short cylinder cut through the plate.for (int i = 0; i < 6; i++) {
for (int j = 0; j < 4; j++) {
try (var hole = Blacksmith.Workplane.xy().extrude(Blacksmith.Profile.circle(2.5), 6).solid()) {
plate = plate.cut(hole.translate(7 + 9.2 * i, 7 + 8.7 * j, -1));
}
}
}
plate.step("plate-holes.stp");
}
}
const { Profile, Solid, Workplane } = require('cadaclysm/blacksmith');
let plate = Solid.cuboid(60, 40, 4).translate(30, 20, 2);
// Six by four holes of radius 2.5, each a short cylinder cut through the plate.for (let i = 0; i < 6; i++) {
for (let j = 0; j < 4; j++) {
const hole = Workplane.xy().extrude(Profile.circle(2.5), 6).solid();
plate = plate.cut(hole.translate(7 + 9.2 * i, 7 + 8.7 * j, -1));
}
}
plate.step('plate-holes.stp');
use cadaclysm_sdk::blacksmith::{Profile, Solid, Unit, Workplane, DEFAULT_TOLERANCE};
fnmain() -> cadaclysm_sdk::Result<()> {
letmut plate = Solid::cuboid(60.0, 40.0, 4.0)?.translate(30.0, 20.0, 2.0)?;
// Six by four holes of radius 2.5, each a short cylinder cut through the plate.for i in0..6 {
for j in0..4 {
let hole = Workplane::xy().extrude(&Profile::circle(2.5)?, 6.0)?.solid()?;
let moved = hole.translate(7.0 + 9.2 * f64::from(i), 7.0 + 8.7 * f64::from(j), -1.0)?;
plate = plate.cut(&moved, DEFAULT_TOLERANCE)?;
}
}
plate.step("plate-holes.stp", None, Unit::Millimetre)
}
import Blacksmith
var plate = try Solid.cuboid(60, 40, 4).translate(30, 20, 2)
// Six by four holes of radius 2.5, each a short cylinder cut through the plate.for i in0..<6 {
for j in0..<4 {
let hole = try Workplane.xy().extrude(Profile.circle(2.5), 6).solid()
plate = try plate.cut(hole.translate(7 + 9.2 * Double(i), 7 + 8.7 * Double(j), -1))
}
}
try plate.step("plate-holes.stp")
local bs = require("cadaclysm_blacksmith")
local Profile, Solid, Workplane = bs.Profile, bs.Solid, bs.Workplane
local plate = Solid.cuboid(60, 40, 4):translate(30, 20, 2)
-- Six by four holes of radius 2.5, each a short cylinder cut through the plate.for i = 0, 5dofor j = 0, 3dolocal hole = Workplane.xy():extrude(Profile.circle(2.5), 6):solid()
plate = plate:cut(hole:translate(7 + 9.2 * i, 7 + 8.7 * j, -1))
endend
plate:step("plate-holes.stp")
Perforated plate
Cut, twenty-four times
A 60 × 40 × 4 plate with a grid of six by four holes, each a short cylinder cut in its turn from an ordinary Python loop. The solid stays closed through every cut, and the STEP carries each hole as two half-cylinders between the plate's faces.
from cadaclysm_blacksmith import Solid
box = Solid.cuboid(30, 30, 30)
hollow = box.shell(3)
# A window through the front wall, to see the void the shell left.
window = Solid.cuboid(10, 8, 10).translate(0, -15, 0)
part = hollow.cut(window)
part.step("hollow-box-window.stp")
using Cadaclysm.Blacksmith;
usingvar box = Solid.Cuboid(30, 30, 30);
usingvar hollow = box.Shell(3);
// A window through the front wall, to see the void the shell left.usingvar window = Solid.Cuboid(10, 8, 10).Translate(0, -15, 0);
usingvar part = hollow.Cut(window);
part.Step("hollow-box-window.stp");
package main
import (
"log""github.com/rdeioris/cadaclysm-sdk/go/blacksmith"
)
func must[T any](v T, err error) T {
if err != nil {
log.Fatal(err)
}
return v
}
funcmain() {
box := must(blacksmith.Cuboid(30, 30, 30))
defer box.Close()
hollow := must(box.Shell(3, nil, blacksmith.FilletTolerance))
defer hollow.Close()
// A window through the front wall, to see the void the shell left.
window := must(must(blacksmith.Cuboid(10, 8, 10)).Translate(0, -15, 0))
defer window.Close()
part := must(hollow.Cut(window, blacksmith.DefaultTolerance))
defer part.Close()
if err := part.Step("hollow-box-window.stp", "", "mm"); err != nil {
log.Fatal(err)
}
}
publicclass HollowBoxWindow {
publicstaticvoidmain(String[] args) {
try (var box = Blacksmith.Solid.cuboid(30, 30, 30);
var hollow = box.shell(3);
// A window through the front wall, to see the void the shell left.var window = Blacksmith.Solid.cuboid(10, 8, 10).translate(0, -15, 0);
var part = hollow.cut(window)) {
part.step("hollow-box-window.stp");
}
}
}
const { Solid } = require('cadaclysm/blacksmith');
const box = Solid.cuboid(30, 30, 30);
const hollow = box.shell(3);
// A window through the front wall, to see the void the shell left.const window = Solid.cuboid(10, 8, 10).translate(0, -15, 0);
const part = hollow.cut(window);
part.step('hollow-box-window.stp');
use cadaclysm_sdk::blacksmith::{Solid, Unit, DEFAULT_TOLERANCE, FILLET_TOLERANCE};
fnmain() -> cadaclysm_sdk::Result<()> {
let block = Solid::cuboid(30.0, 30.0, 30.0)?;
let hollow = block.shell(3.0, &[], FILLET_TOLERANCE)?;
// A window through the front wall, to see the void the shell left.let window = Solid::cuboid(10.0, 8.0, 10.0)?.translate(0.0, -15.0, 0.0)?;
let part = hollow.cut(&window, DEFAULT_TOLERANCE)?;
part.step("hollow-box-window.stp", None, Unit::Millimetre)
}
import Blacksmith
let box = try Solid.cuboid(30, 30, 30)
let hollow = try box.shell(3)
// A window through the front wall, to see the void the shell left.let window = try Solid.cuboid(10, 8, 10).translate(0, -15, 0)
let part = try hollow.cut(window)
try part.step("hollow-box-window.stp")
local Solid = require("cadaclysm_blacksmith").Solid
local box = Solid.cuboid(30, 30, 30)
local hollow = box:shell(3)
-- A window through the front wall, to see the void the shell left.local window = Solid.cuboid(10, 8, 10):translate(0, -15, 0)
local part = hollow:cut(window)
part:step("hollow-box-window.stp")
Hollow box
Shell, then cut
A 30 mm cube shelled to 3 mm walls, which leaves a closed void inside, and a window cut through the front wall to open it. The inner faces are the outer ones offset inwards; the window's four faces run between the two.
import math
from cadaclysm_blacksmith import Profile, Solid
# The bottle's side, a degree-3 spline in the x/z half-plane (x the radius),# closed along the axis so the ends are capped flat.
side = [(7.238, 1.498), (9.221, 3.368), (10.868, 15.965), (7.306, 22.771),
(1.909, 24.951), (3.059, 33.424), (3.591, 33.377), (4.0, 34.0)]
knots = [0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6]
profile = (Profile.path((6, 0)).nurbs_to(side, knots, 3)
.line_to(0, 34).line_to(0, 0).line_to(6, 0).end())
bottle = Solid.revolve(profile, ((0, 0, 0), (0, 0, 1)), 2 * math.pi)
bottle.step("revolve-bottle.stp")
using Cadaclysm.Blacksmith;
// The bottle's side, a degree-3 spline in the x/z half-plane (x the radius),// closed along the axis so the ends are capped flat.var side = new[] { (7.238, 1.498), (9.221, 3.368), (10.868, 15.965), (7.306, 22.771),
(1.909, 24.951), (3.059, 33.424), (3.591, 33.377), (4.0, 34.0) };
var knots = newdouble[] { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6 };
usingvar profile = Profile.Path((6, 0)).NurbsTo(side, knots, 3)
.LineTo(0, 34).LineTo(0, 0).LineTo(6, 0).End();
usingvar bottle = Solid.Revolve(profile, newdouble[] { 0, 0, 0, 0, 0, 1 }, 2 * Math.PI);
bottle.Step("revolve-bottle.stp");
package main
import (
"log""math""github.com/rdeioris/cadaclysm-sdk/go/blacksmith"
)
func must[T any](v T, err error) T {
if err != nil {
log.Fatal(err)
}
return v
}
funcmain() {
// The bottle's side, a degree-3 spline in the x/z half-plane (x the radius),// closed along the axis so the ends are capped flat.
side := [][2]float64{{7.238, 1.498}, {9.221, 3.368}, {10.868, 15.965}, {7.306, 22.771},
{1.909, 24.951}, {3.059, 33.424}, {3.591, 33.377}, {4.0, 34.0}}
knots := []float64{0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6}
profile := must(blacksmith.NewPath(6, 0).NurbsTo(side, knots, 3, nil).
LineTo(0, 34).LineTo(0, 0).LineTo(6, 0).End())
defer profile.Close()
bottle := must(blacksmith.Revolve(profile, [6]float64{0, 0, 0, 0, 0, 1}, 2*math.Pi))
defer bottle.Close()
if err := bottle.Step("revolve-bottle.stp", "", "mm"); err != nil {
log.Fatal(err)
}
}
publicclass RevolveBottle {
publicstaticvoidmain(String[] args) {
// The bottle's side, a degree-3 spline in the x/z half-plane (x the radius),// closed along the axis so the ends are capped flat.double[][] side = {{7.238, 1.498}, {9.221, 3.368}, {10.868, 15.965}, {7.306, 22.771},
{1.909, 24.951}, {3.059, 33.424}, {3.591, 33.377}, {4.0, 34.0}};
double[] knots = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6};
try (var profile = Blacksmith.Profile.path(newdouble[]{6, 0}).nurbsTo(side, knots, 3)
.lineTo(0, 34).lineTo(0, 0).lineTo(6, 0).end();
var bottle = Blacksmith.Solid.revolve(profile, newdouble[]{0, 0, 0, 0, 0, 1}, 2 * Math.PI)) {
bottle.step("revolve-bottle.stp");
}
}
}
const { Profile, Solid } = require('cadaclysm/blacksmith');
// The bottle's side, a degree-3 spline in the x/z half-plane (x the radius),// closed along the axis so the ends are capped flat.const side = [[7.238, 1.498], [9.221, 3.368], [10.868, 15.965], [7.306, 22.771],
[1.909, 24.951], [3.059, 33.424], [3.591, 33.377], [4.0, 34.0]];
const knots = [0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6];
const profile = Profile.path([6, 0]).nurbsTo(side, knots, 3)
.lineTo(0, 34).lineTo(0, 0).lineTo(6, 0).end();
const bottle = Solid.revolve(profile, [[0, 0, 0], [0, 0, 1]], 2 * Math.PI);
bottle.step('revolve-bottle.stp');
use std::f64::consts::PI;
use cadaclysm_sdk::blacksmith::{Path, Solid, Unit};
fnmain() -> cadaclysm_sdk::Result<()> {
// The bottle's side, a degree-3 spline in the x/z half-plane (x the radius),// closed along the axis so the ends are capped flat.let side = [[7.238, 1.498], [9.221, 3.368], [10.868, 15.965], [7.306, 22.771],
[1.909, 24.951], [3.059, 33.424], [3.591, 33.377], [4.0, 34.0]];
let knots = [0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0, 6.0];
let profile = Path::begin([6.0, 0.0])?
.nurbs_to(&side, &knots, 3, None)?
.line_to(0.0, 34.0)?
.line_to(0.0, 0.0)?
.line_to(6.0, 0.0)?
.end()?;
let bottle = Solid::revolve(&profile, &[[0.0, 0.0, 0.0], [0.0, 0.0, 1.0]], 2.0 * PI)?;
bottle.step("revolve-bottle.stp", None, Unit::Millimetre)
}
import Blacksmith
// The bottle's side, a degree-3 spline in the x/z half-plane (x the radius),// closed along the axis so the ends are capped flat.let side: [SIMD2<Double>] = [[7.238, 1.498], [9.221, 3.368], [10.868, 15.965], [7.306, 22.771],
[1.909, 24.951], [3.059, 33.424], [3.591, 33.377], [4.0, 34.0]]
let knots: [Double] = [0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6]
let profile = try Profile.path([6, 0]).nurbsTo(side, knots, 3)
.lineTo(0, 34).lineTo(0, 0).lineTo(6, 0).end()
let bottle = try Solid.revolve(profile, ([0, 0, 0], [0, 0, 1]), 2 * .pi)
try bottle.step("revolve-bottle.stp")
local bs = require("cadaclysm_blacksmith")
local Profile, Solid = bs.Profile, bs.Solid
-- The bottle's side, a degree-3 spline in the x/z half-plane (x the radius),-- closed along the axis so the ends are capped flat.local side = { { 7.238, 1.498 }, { 9.221, 3.368 }, { 10.868, 15.965 }, { 7.306, 22.771 },
{ 1.909, 24.951 }, { 3.059, 33.424 }, { 3.591, 33.377 }, { 4.0, 34.0 } }
local knots = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6 }
local profile = Profile.path({ 6, 0 }):nurbs_to(side, knots, 3)
:line_to(0, 34):line_to(0, 0):line_to(6, 0):end_() -- `end` is a Lua keywordlocal bottle = Solid.revolve(profile, { { 0, 0, 0 }, { 0, 0, 1 } }, 2 * math.pi)
bottle:step("revolve-bottle.stp")
Bottle
Revolve a spline
A bottle's side drawn as one degree-3 spline in the x/z half-plane, closed to the axis with three lines, and turned a full circle about Z. The side is one surface of revolution and the two caps are discs.
use cadaclysm_sdk::blacksmith::{Path, Unit, Workplane};
fnmain() -> cadaclysm_sdk::Result<()> {
// A closed degree-3 spline: the control points after the start, the start last.let points = [[3.427, -2.292], [12.491, -5.040], [23.139, 3.080], [14.951, 16.721],
[1.057, 14.037], [-0.434, 4.100], [0.0, 0.0]];
let knots = [0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0];
let profile = Path::begin([0.0, 0.0])?.nurbs_to(&points, &knots, 3, None)?.end()?;
let prism = Workplane::xy().extrude(&profile, 15.0)?.solid()?;
prism.step("spline-prism.stp", None, Unit::Millimetre)
}
import Blacksmith
// A closed degree-3 spline: the control points after the start, the start last.let points: [SIMD2<Double>] = [[3.427, -2.292], [12.491, -5.040], [23.139, 3.080], [14.951, 16.721],
[1.057, 14.037], [-0.434, 4.100], [0, 0]]
let knots: [Double] = [0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5]
let profile = try Profile.path([0, 0]).nurbsTo(points, knots, 3).end()
let prism = try Workplane.xy().extrude(profile, 15).solid()
try prism.step("spline-prism.stp")
local bs = require("cadaclysm_blacksmith")
local Profile, Workplane = bs.Profile, bs.Workplane
-- A closed degree-3 spline: the control points after the start, the start last.local points = { { 3.427, -2.292 }, { 12.491, -5.040 }, { 23.139, 3.080 }, { 14.951, 16.721 },
{ 1.057, 14.037 }, { -0.434, 4.100 }, { 0, 0 } }
local knots = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5 }
local profile = Profile.path({ 0, 0 }):nurbs_to(points, knots, 3):end_()
local prism = Workplane.xy():extrude(profile, 15):solid()
prism:step("spline-prism.stp")
Spline prism
Extrude a spline
A closed degree-3 spline drawn on the XY plane and pulled up 15. Three faces: the spline's wall, exact in the STEP as the surface it is, and the two flat caps.
import math
from cadaclysm_blacksmith import Profile, Solid, SweepPath
# A full turn about Z, starting on the x axis at radius 10.
path = SweepPath.at((10, 0, 0)).arc((0, 0, 0), (0, 0, 1), 2 * math.pi)
# The profile sits at the path's start, its plane normal to the path (along +Y).
start = ((10, 0, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0))
ring = Solid.sweep(Profile.circle(2), start, path)
ring.step("sweep-ring.stp")
using Cadaclysm.Blacksmith;
// A full turn about Z, starting on the x axis at radius 10.usingvar path = SweepPath.At((10, 0, 0)).Arc((0, 0, 0), (0, 0, 1), 2 * Math.PI);
// The profile sits at the path's start, its plane normal to the path (along +Y).var start = newdouble[] { 10, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0 };
usingvar ring = Solid.Sweep(Profile.Circle(2), start, path);
ring.Step("sweep-ring.stp");
package main
import (
"log""math""github.com/rdeioris/cadaclysm-sdk/go/blacksmith"
)
func must[T any](v T, err error) T {
if err != nil {
log.Fatal(err)
}
return v
}
funcmain() {
// A full turn about Z, starting on the x axis at radius 10.
path := blacksmith.NewSweepPath(10, 0, 0).Arc([3]float64{0, 0, 0}, [3]float64{0, 0, 1}, 2*math.Pi)
defer path.Close()
// The profile sits at the path's start, its plane normal to the path (along +Y).
start := blacksmith.Frame{10, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0}
ring := must(blacksmith.Sweep(must(blacksmith.Circle(2)), start, path))
defer ring.Close()
if err := ring.Step("sweep-ring.stp", "", "mm"); err != nil {
log.Fatal(err)
}
}
publicclass SweepRing {
publicstaticvoidmain(String[] args) {
// A full turn about Z, starting on the x axis at radius 10.try (var path = Blacksmith.SweepPath.at(newdouble[]{10, 0, 0})
.arc(newdouble[]{0, 0, 0}, newdouble[]{0, 0, 1}, 2 * Math.PI);
var profile = Blacksmith.Profile.circle(2)) {
// The profile sits at the path's start, its plane normal to the path (along +Y).double[] start = {10, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0};
try (var ring = Blacksmith.Solid.sweep(profile, start, path)) {
ring.step("sweep-ring.stp");
}
}
}
}
const { Profile, Solid, SweepPath } = require('cadaclysm/blacksmith');
// A full turn about Z, starting on the x axis at radius 10.const path = SweepPath.at([10, 0, 0]).arc([0, 0, 0], [0, 0, 1], 2 * Math.PI);
// The profile sits at the path's start, its plane normal to the path (along +Y).const start = [[10, 0, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0]];
const ring = Solid.sweep(Profile.circle(2), start, path);
ring.step('sweep-ring.stp');
use std::f64::consts::PI;
use cadaclysm_sdk::blacksmith::{Frame, Profile, Solid, SweepPath, Unit};
fnmain() -> cadaclysm_sdk::Result<()> {
// A full turn about Z, starting on the x axis at radius 10.let path = SweepPath::at([10.0, 0.0, 0.0])?.arc([0.0, 0.0, 0.0], [0.0, 0.0, 1.0], 2.0 * PI)?;
// The profile sits at the path's start, its plane normal to the path (along +Y).let start = Frame::new([10.0, 0.0, 0.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0])?;
let ring = Solid::sweep(&Profile::circle(2.0)?, &start, &path)?;
ring.step("sweep-ring.stp", None, Unit::Millimetre)
}
import Blacksmith
// A full turn about Z, starting on the x axis at radius 10.let path = try SweepPath.at([10, 0, 0]).arc([0, 0, 0], [0, 0, 1], 2 * .pi)
// The profile sits at the path's start, its plane normal to the path (along +Y).let start = tryFrame([10, 0, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0])
let ring = try Solid.sweep(Profile.circle(2), start, path)
try ring.step("sweep-ring.stp")
local bs = require("cadaclysm_blacksmith")
local Profile, Solid, SweepPath = bs.Profile, bs.Solid, bs.SweepPath
-- A full turn about Z, starting on the x axis at radius 10.local path = SweepPath.at({ 10, 0, 0 }):arc({ 0, 0, 0 }, { 0, 0, 1 }, 2 * math.pi)
-- The profile sits at the path's start, its plane normal to the path (along +Y).local start = { { 10, 0, 0 }, { 0, 0, 1 }, { 1, 0, 0 }, { 0, 1, 0 } }
local ring = Solid.sweep(Profile.circle(2), start, path)
ring:step("sweep-ring.stp")
Swept ring
Sweep along an arc
A circle of radius 2 carried once round a circle of radius 10, the profile held normal to the path all the way. A torus, in other words, but arrived at by a sweep, whose path may equally be lines and arcs joined end to end.
from cadaclysm_blacksmith import Axis, Profile, Selector, Solid, Workplane
base = Solid.cuboid(30, 30, 5)
pillar = (Workplane.from_solid(base)
.faces(Selector.max(Axis.Z)).workplane()
.extrude(Profile.circle(6), 12).solid())
part = base.join(pillar)
# The joint: the one round edge at the top of the base.
top = base.bounds[1][2]
joint = [e for e in part.edges
ifnot e.is_line andabs(e.segments[0][0][2] - top) < 1e-6]
part = part.fillet(joint, 2)
part.step("pillar-fillet.stp")
using Cadaclysm.Blacksmith;
usingvar slab = Solid.Cuboid(30, 30, 5);
usingvar pillar = Workplane.FromSolid(slab)
.Faces(Selector.Max(Axis.Z)).OnFace()
.Extrude(Profile.Circle(6), 12).Solid();
usingvar joined = slab.Join(pillar);
// The joint: the one round edge at the top of the base.var top = slab.Bounds.Max[2];
var joint = joined.Edges.Where(e => !e.IsLine && Math.Abs(e.Segments[0].A[2] - top) < 1e-6);
usingvar part = joined.Fillet(joint, 2);
part.Step("pillar-fillet.stp");
package main
import (
"log""math""github.com/rdeioris/cadaclysm-sdk/go/blacksmith"
)
func must[T any](v T, err error) T {
if err != nil {
log.Fatal(err)
}
return v
}
funcmain() {
base := must(blacksmith.Cuboid(30, 30, 5))
defer base.Close()
pillar := must(blacksmith.FromSolid(base).
Faces(blacksmith.Max(blacksmith.AxisZ)).OnFace().
Extrude(must(blacksmith.Circle(6)), 12).Solid())
defer pillar.Close()
joined := must(base.Join(pillar, blacksmith.DefaultTolerance))
defer joined.Close()
// The joint: the one round edge at the top of the base.
top := must(base.Bounds()).Max[2]
var joint []intfor _, e := rangemust(joined.Edges()) {
if !e.IsLine() && math.Abs(e.Segments[0][0][2]-top) < 1e-6 {
joint = append(joint, e.Index)
}
}
part := must(joined.Fillet(joint, 2, blacksmith.FilletTolerance))
defer part.Close()
if err := part.Step("pillar-fillet.stp", "", "mm"); err != nil {
log.Fatal(err)
}
}
publicclass PillarFillet {
publicstaticvoidmain(String[] args) {
try (var base = Blacksmith.Solid.cuboid(30, 30, 5);
var pillar = Blacksmith.Workplane.fromSolid(base)
.faces(Blacksmith.Selector.max(Blacksmith.Axis.Z)).onFace()
.extrude(Blacksmith.Profile.circle(6), 12).solid();
var joined = base.join(pillar)) {
// The joint: the one round edge at the top of the base.double top = base.bounds().max()[2];
var joint = joined.edges().stream()
.filter(e -> !e.isLine() && Math.abs(e.segments()[0].a()[2] - top) < 1e-6)
.toList();
try (var part = joined.fillet(joint, 2)) {
part.step("pillar-fillet.stp");
}
}
}
}
const { Axis, Profile, Selector, Solid, Workplane } = require('cadaclysm/blacksmith');
const base = Solid.cuboid(30, 30, 5);
const pillar = Workplane.fromSolid(base)
.faces(Selector.max(Axis.Z)).workplane()
.extrude(Profile.circle(6), 12).solid();
let part = base.join(pillar);
// The joint: the one round edge at the top of the base.const top = base.bounds[1][2];
const joint = part.edges().filter((e) => !e.isLine && Math.abs(e.segments[0][0][2] - top) < 1e-6);
part = part.fillet(joint, 2);
part.step('pillar-fillet.stp');
use cadaclysm_sdk::blacksmith::{Axis, Profile, Selector, Solid, Unit, Workplane, DEFAULT_TOLERANCE, FILLET_TOLERANCE};
fnmain() -> cadaclysm_sdk::Result<()> {
let base = Solid::cuboid(30.0, 30.0, 5.0)?;
let pillar = Workplane::from_solid(&base)
.faces(&Selector::Max(Axis::Z))?
.on_face()?
.extrude(&Profile::circle(6.0)?, 12.0)?
.solid()?;
let joined = base.join(&pillar, DEFAULT_TOLERANCE)?;
// The joint: the one round edge at the top of the base.let top = base.bounds()?.1[2];
let joint: Vec<u32> = joined
.edges()?
.iter()
.filter(|e| !e.is_line() && (e.segments[0][0][2] - top).abs() < 1e-6)
.map(|e| e.index)
.collect();
let part = joined.fillet(&joint, 2.0, FILLET_TOLERANCE)?;
part.step("pillar-fillet.stp", None, Unit::Millimetre)
}
import Blacksmith
let base = try Solid.cuboid(30, 30, 5)
let pillar = try Workplane.fromSolid(base)
.faces(.max(.z)).workplane()
.extrude(Profile.circle(6), 12).solid()
var part = try base.join(pillar)
// The joint: the one round edge at the top of the base.let top = try base.bounds.max.z
let joint = try part.edges.filter { !$0.isLine && abs($0.segments[0].start.z - top) < 1e-6 }
part = try part.fillet(joint, 2)
try part.step("pillar-fillet.stp")
local bs = require("cadaclysm_blacksmith")
local Axis, Profile, Selector, Solid, Workplane = bs.Axis, bs.Profile, bs.Selector, bs.Solid, bs.Workplane
local base = Solid.cuboid(30, 30, 5)
local pillar = Workplane.from_solid(base)
:faces(Selector.max(Axis.Z)):workplane()
:extrude(Profile.circle(6), 12):solid()
local part = base:join(pillar)
-- The joint: the one round edge at the top of the base.local top = base.bounds[2][3]
local joint = {}
for _, e inipairs(part.edges) doifnot e.is_line and math.abs(e.segments[1][1][3] - top) < 1e-6then
joint[#joint + 1] = e
endend
part = part:fillet(joint, 2)
part:step("pillar-fillet.stp")
Pillar on a base
Join, then fillet the joint
A round pillar raised from the top face of a 30 × 30 × 5 base and joined to it, then the circle where they meet rounded at 2. The fillet is a torus band, tangent to the base's plane on one side and to the pillar's cylinder on the other.