refactor: add DesignIR distillation pipeline
@@ -1,118 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "Modify the existing build123d connecting rod from the CAD Viewer selection: add a 2 mm wide blind slot along the selected segment on face f18, regenerate STEP, STL, and CAD Viewer mesh/topology assets.",
|
||||
"route": {
|
||||
"selected_backend": "build123d",
|
||||
"runner_skill": "cad",
|
||||
"project": "text-to-cad",
|
||||
"confidence": "high",
|
||||
"fallback_order": [
|
||||
"simplecadapi",
|
||||
"cadam"
|
||||
],
|
||||
"operation": "modify",
|
||||
"modification_strategy": "native_parameter_editing",
|
||||
"decision_path": "route-decision.json"
|
||||
},
|
||||
"source": {
|
||||
"path": "connecting_rod.py",
|
||||
"format": "python",
|
||||
"backend": "build123d"
|
||||
},
|
||||
"artifacts": [
|
||||
{
|
||||
"path": "connecting_rod.step",
|
||||
"role": "primary"
|
||||
},
|
||||
{
|
||||
"path": "connecting_rod.stl",
|
||||
"role": "secondary"
|
||||
},
|
||||
{
|
||||
"path": ".connecting_rod.step.glb",
|
||||
"role": "viewer_mesh_topology"
|
||||
},
|
||||
{
|
||||
"path": "connecting_rod_slot_review_20260723T100007Z.png",
|
||||
"role": "verification_snapshot"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"center_distance_mm": 120.0,
|
||||
"thickness_mm": 14.0,
|
||||
"big_end_outer_diameter_mm": 56.0,
|
||||
"big_end_bore_diameter_mm": 36.0,
|
||||
"small_end_outer_diameter_mm": 36.0,
|
||||
"small_end_bore_diameter_mm": 20.0,
|
||||
"web_width_mm": 24.0,
|
||||
"pocket_depth_each_side_mm": 3.0,
|
||||
"viewer_slot_start_mm": [
|
||||
-28.73179347578467,
|
||||
-0.3844822039559189
|
||||
],
|
||||
"viewer_slot_end_mm": [
|
||||
24.36043904920138,
|
||||
-0.24367243243227724
|
||||
],
|
||||
"viewer_slot_surface_z_mm": 11.0,
|
||||
"viewer_slot_width_mm": 2.0,
|
||||
"viewer_slot_blind_depth_mm": 2.0,
|
||||
"viewer_slot_bottom_z_mm": 9.0
|
||||
},
|
||||
"experience": {
|
||||
"library": "../../../cad-experience-library/library.json",
|
||||
"context_kind": "generalized_cad_experience_query",
|
||||
"methods_applied": []
|
||||
},
|
||||
"assumptions": [
|
||||
"The selected face f18 is the existing top-pocket floor at z=11 mm, so the blind slot cuts inward into the material from z=11 mm down to z=9 mm.",
|
||||
"The CAD edit intent marks depth as blind but does not provide a numeric depth, so a conservative 2 mm blind depth was used.",
|
||||
"This V1 sample demonstrates routing and editability rather than a production-rated engine component.",
|
||||
"Material, fatigue loads, bearing fits, lubrication, fasteners, tolerances, and split big-end construction are intentionally out of scope."
|
||||
],
|
||||
"validation": [
|
||||
{
|
||||
"check": "STEP generation from editable source",
|
||||
"result": "scripts/cad step regenerated connecting_rod.step, connecting_rod.stl, and hidden CAD Viewer GLB/topology assets from connecting_rod.py.",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"check": "closed solid topology",
|
||||
"result": {
|
||||
"kind": "part",
|
||||
"shape_count": 1,
|
||||
"face_count": 23,
|
||||
"edge_count": 54,
|
||||
"bounds_mm": [
|
||||
165.978199,
|
||||
55.977382,
|
||||
14.0
|
||||
]
|
||||
},
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"check": "selected-face slot placement",
|
||||
"result": "Original selected face f18 remains the top-pocket floor at z=11 mm; new slot bottom face f23 is centered at [-2.185677, -0.314077, 9.0].",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"check": "blind slot depth",
|
||||
"result": "Slot side faces span z=9.0 mm to z=11.0 mm.",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"check": "slot width",
|
||||
"result": "Slot end faces are cylinders with radius 1.0 mm, matching the requested 2.0 mm slot width.",
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"check": "snapshot review",
|
||||
"result": "Isometric snapshot shows the connecting rod, existing top pocket, and the new narrow blind slot without visible breakage or disconnected geometry.",
|
||||
"status": "pass"
|
||||
}
|
||||
],
|
||||
"viewer_links": [
|
||||
"http://127.0.0.1:5175/?dir=%2FUsers%2Flk%2FProjects%2FcadSet%2Ftext-to-cad%2Fmodels%2Fcad-router-v1&file=connecting_rod.step"
|
||||
]
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "Generate a parameterized perforated vase for 3D printing",
|
||||
"route": {
|
||||
"selected_backend": "cadam",
|
||||
"project": "CADAM",
|
||||
"runner_skill": "cad-router",
|
||||
"adapter": "skills/cad-router/scripts/cadam_compile.mjs",
|
||||
"fallback_order": [
|
||||
"build123d",
|
||||
"simplecadapi"
|
||||
],
|
||||
"workflow_profiles": []
|
||||
},
|
||||
"source": {
|
||||
"path": "cadam_parametric_vase.scad",
|
||||
"format": "scad",
|
||||
"backend": "cadam"
|
||||
},
|
||||
"artifacts": [
|
||||
{
|
||||
"path": "cadam_parametric_vase.stl",
|
||||
"role": "primary"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"height_mm": 80,
|
||||
"base_radius_mm": 30,
|
||||
"top_radius_mm": 24,
|
||||
"wall_mm": 2.4,
|
||||
"base_mm": 3
|
||||
},
|
||||
"assumptions": [
|
||||
"The repeated perforations are decorative and are not load-bearing features."
|
||||
],
|
||||
"validation": [
|
||||
{
|
||||
"check": "CADAM OpenSCAD WASM compile",
|
||||
"status": "passed",
|
||||
"details": "exit code 0; manifold backend reported NoError; 3816 vertices and 7868 facets"
|
||||
},
|
||||
{
|
||||
"check": "CAD Viewer review",
|
||||
"status": "passed",
|
||||
"details": "STL loaded from the task-scoped cad-router-v1 directory"
|
||||
}
|
||||
],
|
||||
"project_contributions": {
|
||||
"text-to-cad": "router, artifact contract, validation, and CAD Viewer",
|
||||
"SimpleCADAPI": "available specialist mechanical fallback",
|
||||
"CADAM": "SCAD source and OpenSCAD-WASM mesh execution"
|
||||
},
|
||||
"viewer_links": [
|
||||
"http://127.0.0.1:4178/?dir=%2FUsers%2Fjerry%2Flinkhand%2FCadSet%2Ftext-to-cad%2Fmodels%2Fcad-router-v1&file=cadam_parametric_vase.stl"
|
||||
]
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// CADAM/OpenSCAD-WASM route sample for CAD Router V1.
|
||||
$fn = 96;
|
||||
|
||||
height = 80;
|
||||
base_radius = 30;
|
||||
top_radius = 24;
|
||||
wall = 2.4;
|
||||
base = 3;
|
||||
|
||||
difference() {
|
||||
cylinder(h = height, r1 = base_radius, r2 = top_radius);
|
||||
translate([0, 0, base])
|
||||
cylinder(
|
||||
h = height,
|
||||
r1 = base_radius - wall,
|
||||
r2 = top_radius - wall
|
||||
);
|
||||
|
||||
for (z = [14 : 14 : 70]) {
|
||||
for (angle = [0 : 30 : 330]) {
|
||||
rotate([0, 0, angle + z * 0.75])
|
||||
translate([base_radius - 1.0 - z * 0.07, 0, z])
|
||||
rotate([0, 90, 0])
|
||||
cylinder(h = wall + 5, r = 2.2, center = true, $fn = 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "Regenerate the current compact guided-cylinder housing using only promoted generalized CAD experience while preserving the existing parameterized geometry and enlarged central bore.",
|
||||
"route": {
|
||||
"selected_backend": "build123d",
|
||||
"runner_skill": "cad",
|
||||
"project": "text-to-cad",
|
||||
"fallback_order": [
|
||||
"simplecadapi",
|
||||
"cadam"
|
||||
],
|
||||
"workflow_profiles": [
|
||||
"requirement_refinement",
|
||||
"visual_repair"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"model_spec": "model-spec.json",
|
||||
"path": "compact_guided_cylinder.py",
|
||||
"format": "python",
|
||||
"backend": "build123d"
|
||||
},
|
||||
"artifacts": [
|
||||
{
|
||||
"path": "compact_guided_cylinder.step",
|
||||
"role": "primary"
|
||||
},
|
||||
{
|
||||
"path": "compact_guided_cylinder.stl",
|
||||
"role": "secondary"
|
||||
}
|
||||
],
|
||||
"parameter_source": "model-spec.json",
|
||||
"experience": {
|
||||
"library": "../../../../cad-experience-library/library.json",
|
||||
"context_kind": "generalized_cad_experience_query",
|
||||
"query_scope": "global",
|
||||
"promoted_methods_found": 0,
|
||||
"methods_applied": [],
|
||||
"result": "No promoted generalized methods matched; candidate experiences were intentionally excluded from generation."
|
||||
},
|
||||
"assumptions": [
|
||||
"The image has no absolute dimensions; millimetre dimensions preserve visible proportions only.",
|
||||
"The product is represented as a three-body compound: main extrusion plus two end caps.",
|
||||
"The four top holes are modeled through the main body because the bottom view shows matching circles.",
|
||||
"The four large circles on each end are treated as protruding tie-rod ends.",
|
||||
"The central bore radius was doubled from 4.5 mm to 9 mm; the collar outer diameter was increased from 17 mm to 26 mm to retain a 4 mm radial wall.",
|
||||
"This is concept geometry, not a pressure-rated or manufacturing-certified pneumatic cylinder."
|
||||
],
|
||||
"validation": [
|
||||
{
|
||||
"check": "STEP generation",
|
||||
"result": "passed",
|
||||
"detail": "Generated a labeled three-body assembly and STL sidecar from the parameterized Python source."
|
||||
},
|
||||
{
|
||||
"check": "Bounding box",
|
||||
"result": "passed",
|
||||
"detail": "138 x 60 x 39 mm; dominant axis X."
|
||||
},
|
||||
{
|
||||
"check": "Topology",
|
||||
"result": "passed",
|
||||
"detail": "61 faces and 156 edges after the side-groove repair."
|
||||
},
|
||||
{
|
||||
"check": "Visual review",
|
||||
"result": "passed",
|
||||
"detail": "Reviewed regenerated isometric and top snapshots. Geometry remains visually consistent with the current parameterized source, including the enlarged central bore and four-hole pattern."
|
||||
},
|
||||
{
|
||||
"check": "Experience isolation",
|
||||
"result": "passed",
|
||||
"detail": "The router reported zero generalized methods. No candidate experience, parser input, parser output, private case JSON, source dimensions, or coordinates were used."
|
||||
},
|
||||
{
|
||||
"check": "JSON parameter rebuild",
|
||||
"result": "passed",
|
||||
"detail": "The STEP and STL were regenerated from the part-local model-spec.json through the native Python generator."
|
||||
}
|
||||
],
|
||||
"viewer_links": [
|
||||
"http://127.0.0.1:4179/?dir=%2FUsers%2Fjerry%2Flinkhand%2FCadSet%2Ftext-to-cad%2Fmodels%2Fcad-router-v1%2Fcompact_guided_cylinder_v1&file=compact_guided_cylinder.step",
|
||||
"http://127.0.0.1:4179/?dir=%2FUsers%2Fjerry%2Flinkhand%2FCadSet%2Ftext-to-cad%2Fmodels%2Fcad-router-v1%2Fcompact_guided_cylinder_v1&file=compact_guided_cylinder.stl"
|
||||
]
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
"""Image-inferred compact guided-cylinder housing.
|
||||
|
||||
The reference contains no dimensions, so the named dimensions below preserve
|
||||
its visible proportions rather than claiming a production drawing.
|
||||
|
||||
Coordinate convention:
|
||||
- X: long axis
|
||||
- Y: width
|
||||
- Z: height, with the lowest end-cap face at Z = 0
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from build123d import Align, Box, Compound, Cylinder, Pos
|
||||
|
||||
|
||||
def _model_parameters():
|
||||
spec_path = Path(__file__).with_name("model-spec.json")
|
||||
payload = json.loads(spec_path.read_text(encoding="utf-8"))
|
||||
return {
|
||||
name: float(entry["value"])
|
||||
for name, entry in payload["parameters"].items()
|
||||
}
|
||||
|
||||
|
||||
PARAMETERS = _model_parameters()
|
||||
|
||||
|
||||
def _parameter(name: str) -> float:
|
||||
return PARAMETERS[name]
|
||||
|
||||
|
||||
# Overall proportions inferred from the reference image (millimetres).
|
||||
CORE_LENGTH = _parameter("core_length")
|
||||
CORE_WIDTH = _parameter("core_width")
|
||||
CORE_BOTTOM_Z = _parameter("core_bottom_z")
|
||||
CORE_HEIGHT = _parameter("core_height")
|
||||
END_CAP_THICKNESS = _parameter("end_cap_thickness")
|
||||
END_CAP_WIDTH = _parameter("end_cap_width")
|
||||
END_CAP_HEIGHT = _parameter("end_cap_height")
|
||||
|
||||
# Two shallow longitudinal relief grooves on both long side faces.
|
||||
SIDE_GROOVE_DEPTH = _parameter("side_groove_depth")
|
||||
SIDE_GROOVE_HEIGHT = _parameter("side_groove_height")
|
||||
SIDE_GROOVE_Z = (12.0, 24.0)
|
||||
|
||||
# Four inferred through mounting holes on the top/bottom pattern.
|
||||
MOUNT_HOLE_DIAMETER = _parameter("mount_hole_diameter")
|
||||
MOUNT_HOLE_X = _parameter("mount_hole_x")
|
||||
MOUNT_HOLE_Y = _parameter("mount_hole_y")
|
||||
|
||||
# Central top port and raised collar.
|
||||
PORT_BORE_DIAMETER = _parameter("port_bore_diameter")
|
||||
PORT_COLLAR_OUTER_DIAMETER = _parameter("port_collar_outer_diameter")
|
||||
PORT_COLLAR_HEIGHT = _parameter("port_collar_height")
|
||||
|
||||
# Four visible tie-rod ends on each end cap.
|
||||
TIE_ROD_END_DIAMETER = _parameter("tie_rod_end_diameter")
|
||||
TIE_ROD_END_PROTRUSION = _parameter("tie_rod_end_protrusion")
|
||||
TIE_ROD_Y = _parameter("tie_rod_y")
|
||||
TIE_ROD_Z = (7.0, 31.0)
|
||||
|
||||
# Small blind pilot/port visible on both end faces.
|
||||
END_FACE_HOLE_DIAMETER = _parameter("end_face_hole_diameter")
|
||||
END_FACE_HOLE_DEPTH = _parameter("end_face_hole_depth")
|
||||
END_FACE_HOLE_Z = _parameter("end_face_hole_z")
|
||||
|
||||
|
||||
END_CAP_CENTER_X = CORE_LENGTH / 2.0 + END_CAP_THICKNESS / 2.0
|
||||
TOTAL_LENGTH = CORE_LENGTH + 2.0 * END_CAP_THICKNESS
|
||||
VISIBLE_LENGTH = TOTAL_LENGTH + 2.0 * TIE_ROD_END_PROTRUSION
|
||||
TOTAL_HEIGHT = END_CAP_HEIGHT + PORT_COLLAR_HEIGHT
|
||||
|
||||
|
||||
def _x_cylinder(
|
||||
length: float,
|
||||
diameter: float,
|
||||
center_x: float,
|
||||
center_y: float,
|
||||
center_z: float,
|
||||
):
|
||||
"""Create an X-axis cylinder centered at the requested location."""
|
||||
return Pos(center_x, center_y, center_z) * Cylinder(
|
||||
diameter / 2.0,
|
||||
length,
|
||||
align=(Align.CENTER, Align.CENTER, Align.CENTER),
|
||||
rotation=(0.0, 90.0, 0.0),
|
||||
)
|
||||
|
||||
|
||||
def _make_core():
|
||||
"""Main extrusion with side grooves, top pattern, and central through port."""
|
||||
core = Pos(0.0, 0.0, CORE_BOTTOM_Z) * Box(
|
||||
CORE_LENGTH,
|
||||
CORE_WIDTH,
|
||||
CORE_HEIGHT,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
# Cut two crisp grooves into each long side, stopping at the end-cap seams.
|
||||
for groove_z in SIDE_GROOVE_Z:
|
||||
groove_center_y = CORE_WIDTH / 2.0 - SIDE_GROOVE_DEPTH / 2.0 + 0.2
|
||||
front_tool = Pos(0.0, groove_center_y, groove_z) * Box(
|
||||
CORE_LENGTH + 1.0,
|
||||
SIDE_GROOVE_DEPTH + 0.4,
|
||||
SIDE_GROOVE_HEIGHT,
|
||||
align=(Align.CENTER, Align.CENTER, Align.CENTER),
|
||||
)
|
||||
back_tool = Pos(0.0, -groove_center_y, groove_z) * Box(
|
||||
CORE_LENGTH + 1.0,
|
||||
SIDE_GROOVE_DEPTH + 0.4,
|
||||
SIDE_GROOVE_HEIGHT,
|
||||
align=(Align.CENTER, Align.CENTER, Align.CENTER),
|
||||
)
|
||||
core = core - front_tool - back_tool
|
||||
|
||||
# Through mounting pattern visible from top and bottom in the reference.
|
||||
for x_pos in (-MOUNT_HOLE_X, MOUNT_HOLE_X):
|
||||
for y_pos in (-MOUNT_HOLE_Y, MOUNT_HOLE_Y):
|
||||
hole = Pos(x_pos, y_pos, -1.0) * Cylinder(
|
||||
MOUNT_HOLE_DIAMETER / 2.0,
|
||||
TOTAL_HEIGHT + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
core = core - hole
|
||||
|
||||
port_hole = Pos(0.0, 0.0, -1.0) * Cylinder(
|
||||
PORT_BORE_DIAMETER / 2.0,
|
||||
TOTAL_HEIGHT + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
core = core - port_hole
|
||||
|
||||
collar = Pos(0.0, 0.0, CORE_BOTTOM_Z + CORE_HEIGHT - 0.1) * Cylinder(
|
||||
PORT_COLLAR_OUTER_DIAMETER / 2.0,
|
||||
PORT_COLLAR_HEIGHT + 0.1,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
collar = collar - Pos(0.0, 0.0, CORE_BOTTOM_Z + CORE_HEIGHT - 1.0) * Cylinder(
|
||||
PORT_BORE_DIAMETER / 2.0,
|
||||
PORT_COLLAR_HEIGHT + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
core = core + collar
|
||||
core.label = "extruded_cylinder_body"
|
||||
return core
|
||||
|
||||
|
||||
def _make_end_cap(side: int):
|
||||
"""End plate with four protruding tie-rod ends and one blind face hole."""
|
||||
center_x = side * END_CAP_CENTER_X
|
||||
cap = Pos(center_x, 0.0, 0.0) * Box(
|
||||
END_CAP_THICKNESS,
|
||||
END_CAP_WIDTH,
|
||||
END_CAP_HEIGHT,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
boss_center_x = side * (
|
||||
TOTAL_LENGTH / 2.0 + TIE_ROD_END_PROTRUSION / 2.0 - 0.5
|
||||
)
|
||||
for y_pos in (-TIE_ROD_Y, TIE_ROD_Y):
|
||||
for z_pos in TIE_ROD_Z:
|
||||
cap = cap + _x_cylinder(
|
||||
TIE_ROD_END_PROTRUSION + 1.0,
|
||||
TIE_ROD_END_DIAMETER,
|
||||
boss_center_x,
|
||||
y_pos,
|
||||
z_pos,
|
||||
)
|
||||
|
||||
# Blind end-face pilot: overshoot the outside face but stop inside the cap.
|
||||
hole_center_x = side * (
|
||||
TOTAL_LENGTH / 2.0 - END_FACE_HOLE_DEPTH / 2.0 + 0.5
|
||||
)
|
||||
cap = cap - _x_cylinder(
|
||||
END_FACE_HOLE_DEPTH + 1.0,
|
||||
END_FACE_HOLE_DIAMETER,
|
||||
hole_center_x,
|
||||
0.0,
|
||||
END_FACE_HOLE_Z,
|
||||
)
|
||||
cap.label = "right_end_cap" if side > 0 else "left_end_cap"
|
||||
return cap
|
||||
|
||||
|
||||
def gen_step():
|
||||
"""Return a labeled three-body STEP-ready compound."""
|
||||
core = _make_core()
|
||||
left_cap = _make_end_cap(-1)
|
||||
right_cap = _make_end_cap(1)
|
||||
|
||||
model = Compound(children=[core, left_cap, right_cap])
|
||||
model.label = "compact_guided_cylinder_v1"
|
||||
return model
|
||||
@@ -1,149 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"model_spec_kind": "parametric_cad_model",
|
||||
"model_id": "compact_guided_cylinder",
|
||||
"units": "mm",
|
||||
"reconstruction": {
|
||||
"mode": "native_generator",
|
||||
"generator": {
|
||||
"path": "compact_guided_cylinder.py",
|
||||
"entrypoint": "gen_step"
|
||||
}
|
||||
},
|
||||
"parameters": {
|
||||
"core_length": {
|
||||
"value": 116.0,
|
||||
"unit": "mm",
|
||||
"role": "main_body_length"
|
||||
},
|
||||
"core_width": {
|
||||
"value": 56.0,
|
||||
"unit": "mm",
|
||||
"role": "main_body_width"
|
||||
},
|
||||
"core_bottom_z": {
|
||||
"value": 2.0,
|
||||
"unit": "mm",
|
||||
"role": "main_body_base_offset"
|
||||
},
|
||||
"core_height": {
|
||||
"value": 34.0,
|
||||
"unit": "mm",
|
||||
"role": "main_body_height"
|
||||
},
|
||||
"end_cap_thickness": {
|
||||
"value": 8.0,
|
||||
"unit": "mm",
|
||||
"role": "end_cap_thickness"
|
||||
},
|
||||
"end_cap_width": {
|
||||
"value": 60.0,
|
||||
"unit": "mm",
|
||||
"role": "end_cap_width"
|
||||
},
|
||||
"end_cap_height": {
|
||||
"value": 38.0,
|
||||
"unit": "mm",
|
||||
"role": "end_cap_height"
|
||||
},
|
||||
"side_groove_depth": {
|
||||
"value": 1.8,
|
||||
"unit": "mm",
|
||||
"role": "longitudinal_groove_depth"
|
||||
},
|
||||
"side_groove_height": {
|
||||
"value": 2.0,
|
||||
"unit": "mm",
|
||||
"role": "longitudinal_groove_height"
|
||||
},
|
||||
"mount_hole_diameter": {
|
||||
"value": 4.5,
|
||||
"unit": "mm",
|
||||
"role": "mounting_hole_diameter"
|
||||
},
|
||||
"mount_hole_x": {
|
||||
"value": 32.0,
|
||||
"unit": "mm",
|
||||
"role": "mounting_pattern_half_spacing_x"
|
||||
},
|
||||
"mount_hole_y": {
|
||||
"value": 16.0,
|
||||
"unit": "mm",
|
||||
"role": "mounting_pattern_half_spacing_y"
|
||||
},
|
||||
"port_bore_diameter": {
|
||||
"value": 18.0,
|
||||
"unit": "mm",
|
||||
"role": "central_port_bore_diameter"
|
||||
},
|
||||
"port_collar_outer_diameter": {
|
||||
"value": 26.0,
|
||||
"unit": "mm",
|
||||
"role": "central_port_collar_outer_diameter"
|
||||
},
|
||||
"port_collar_height": {
|
||||
"value": 3.0,
|
||||
"unit": "mm",
|
||||
"role": "central_port_collar_height"
|
||||
},
|
||||
"tie_rod_end_diameter": {
|
||||
"value": 12.0,
|
||||
"unit": "mm",
|
||||
"role": "tie_rod_end_diameter"
|
||||
},
|
||||
"tie_rod_end_protrusion": {
|
||||
"value": 3.0,
|
||||
"unit": "mm",
|
||||
"role": "tie_rod_end_protrusion"
|
||||
},
|
||||
"tie_rod_y": {
|
||||
"value": 24.0,
|
||||
"unit": "mm",
|
||||
"role": "tie_rod_pattern_half_spacing_y"
|
||||
},
|
||||
"end_face_hole_diameter": {
|
||||
"value": 5.5,
|
||||
"unit": "mm",
|
||||
"role": "end_face_blind_hole_diameter"
|
||||
},
|
||||
"end_face_hole_depth": {
|
||||
"value": 6.0,
|
||||
"unit": "mm",
|
||||
"role": "end_face_blind_hole_depth"
|
||||
},
|
||||
"end_face_hole_z": {
|
||||
"value": 14.0,
|
||||
"unit": "mm",
|
||||
"role": "end_face_blind_hole_height"
|
||||
}
|
||||
},
|
||||
"feature_groups": [
|
||||
{
|
||||
"id": "main_body",
|
||||
"kind": "prismatic_body"
|
||||
},
|
||||
{
|
||||
"id": "mounting_pattern",
|
||||
"kind": "repeated_axial_hole_pattern",
|
||||
"parameters": [
|
||||
"mount_hole_diameter",
|
||||
"mount_hole_x",
|
||||
"mount_hole_y"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "central_port",
|
||||
"kind": "raised_collar_with_passage",
|
||||
"parameters": [
|
||||
"port_bore_diameter",
|
||||
"port_collar_outer_diameter",
|
||||
"port_collar_height"
|
||||
]
|
||||
}
|
||||
],
|
||||
"modifications": [],
|
||||
"outputs": {
|
||||
"step": "compact_guided_cylinder.step",
|
||||
"stl": "compact_guided_cylinder.stl"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 253 KiB |
|
Before Width: | Height: | Size: 316 KiB |
|
Before Width: | Height: | Size: 322 KiB |
|
Before Width: | Height: | Size: 322 KiB |
|
Before Width: | Height: | Size: 322 KiB |
|
Before Width: | Height: | Size: 370 KiB |
|
Before Width: | Height: | Size: 431 KiB |
|
Before Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 80 KiB |
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"input": "compact_guided_cylinder.step",
|
||||
"mode": "view",
|
||||
"outputs": [
|
||||
{
|
||||
"path": "review/iso.png",
|
||||
"camera": "iso"
|
||||
},
|
||||
{
|
||||
"path": "review/iso_opposite.png",
|
||||
"camera": {
|
||||
"direction": [
|
||||
-1,
|
||||
1,
|
||||
-0.8
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "review/top.png",
|
||||
"camera": "top"
|
||||
},
|
||||
{
|
||||
"path": "review/front.png",
|
||||
"camera": "front"
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"mode": "solid",
|
||||
"projection": "orthographic"
|
||||
},
|
||||
"render": {
|
||||
"viewLabels": true,
|
||||
"padding": 0.12,
|
||||
"sizeProfile": "diagnostic"
|
||||
}
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
"""Parametric V1 connecting-rod sample routed to the build123d backend."""
|
||||
|
||||
from math import atan2, degrees, hypot
|
||||
|
||||
from build123d import (
|
||||
Align,
|
||||
Box,
|
||||
BuildPart,
|
||||
BuildSketch,
|
||||
Cylinder,
|
||||
Location,
|
||||
Locations,
|
||||
Mode,
|
||||
Plane,
|
||||
SlotOverall,
|
||||
extrude,
|
||||
fillet,
|
||||
)
|
||||
|
||||
|
||||
CENTER_DISTANCE = 120.0
|
||||
THICKNESS = 14.0
|
||||
|
||||
BIG_END_OUTER_DIAMETER = 56.0
|
||||
BIG_END_BORE_DIAMETER = 36.0
|
||||
SMALL_END_OUTER_DIAMETER = 36.0
|
||||
SMALL_END_BORE_DIAMETER = 20.0
|
||||
|
||||
WEB_WIDTH = 24.0
|
||||
POCKET_LENGTH = 72.0
|
||||
POCKET_WIDTH = 12.0
|
||||
POCKET_DEPTH = 3.0
|
||||
|
||||
VIEWER_SLOT_START = (-28.73179347578467, -0.3844822039559189)
|
||||
VIEWER_SLOT_END = (24.36043904920138, -0.24367243243227724)
|
||||
VIEWER_SLOT_SURFACE_Z = THICKNESS - POCKET_DEPTH
|
||||
VIEWER_SLOT_WIDTH = 2.0
|
||||
VIEWER_SLOT_BLIND_DEPTH = 2.0
|
||||
VIEWER_EDGE_E14_FILLET_RADIUS = 1.0
|
||||
VIEWER_HOLE_CENTER = (-22.122781376227962, -9.435525387895417)
|
||||
VIEWER_HOLE_DIAMETER = 6.0
|
||||
VIEWER_HOLE_BLIND_DEPTH = 6.0
|
||||
VIEWER_HOLE_SURFACE_Z = THICKNESS
|
||||
VIEWER_HOLE_BOOLEAN_OVERTRAVEL = 0.2
|
||||
|
||||
VIEWER_SLOT_CENTER = (
|
||||
(VIEWER_SLOT_START[0] + VIEWER_SLOT_END[0]) / 2.0,
|
||||
(VIEWER_SLOT_START[1] + VIEWER_SLOT_END[1]) / 2.0,
|
||||
)
|
||||
VIEWER_SLOT_LENGTH = hypot(
|
||||
VIEWER_SLOT_END[0] - VIEWER_SLOT_START[0],
|
||||
VIEWER_SLOT_END[1] - VIEWER_SLOT_START[1],
|
||||
)
|
||||
VIEWER_SLOT_ROTATION = degrees(
|
||||
atan2(
|
||||
VIEWER_SLOT_END[1] - VIEWER_SLOT_START[1],
|
||||
VIEWER_SLOT_END[0] - VIEWER_SLOT_START[0],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _viewer_edge_e14(part):
|
||||
"""Select the big-end top outer edge selected in CAD Viewer as e14."""
|
||||
selected_edges = []
|
||||
for edge in part.edges():
|
||||
try:
|
||||
edge_radius = edge.radius
|
||||
edge_center = edge.arc_center
|
||||
edge_normal = edge.normal()
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if abs(edge_radius - BIG_END_OUTER_DIAMETER / 2.0) > 0.05:
|
||||
continue
|
||||
if abs(edge_center.X + CENTER_DISTANCE / 2.0) > 0.05:
|
||||
continue
|
||||
if abs(edge_center.Y) > 0.05:
|
||||
continue
|
||||
if abs(edge_center.Z - THICKNESS) > 0.05:
|
||||
continue
|
||||
if abs(edge_normal.Z) < 1.0 - 1e-4:
|
||||
continue
|
||||
selected_edges.append(edge)
|
||||
|
||||
if len(selected_edges) != 1:
|
||||
raise RuntimeError(f"Expected one viewer-selected e14 edge, found {len(selected_edges)}")
|
||||
return selected_edges
|
||||
|
||||
|
||||
def gen_step():
|
||||
"""Return a closed, STEP-ready connecting-rod solid in millimeters."""
|
||||
half_distance = CENTER_DISTANCE / 2.0
|
||||
|
||||
with BuildPart() as rod:
|
||||
with Locations(Location((-half_distance, 0.0, 0.0))):
|
||||
Cylinder(
|
||||
radius=BIG_END_OUTER_DIAMETER / 2.0,
|
||||
height=THICKNESS,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
with Locations(Location((half_distance, 0.0, 0.0))):
|
||||
Cylinder(
|
||||
radius=SMALL_END_OUTER_DIAMETER / 2.0,
|
||||
height=THICKNESS,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
Box(
|
||||
CENTER_DISTANCE,
|
||||
WEB_WIDTH,
|
||||
THICKNESS,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
with Locations(Location((-half_distance, 0.0, -1.0))):
|
||||
Cylinder(
|
||||
radius=BIG_END_BORE_DIAMETER / 2.0,
|
||||
height=THICKNESS + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
with Locations(Location((half_distance, 0.0, -1.0))):
|
||||
Cylinder(
|
||||
radius=SMALL_END_BORE_DIAMETER / 2.0,
|
||||
height=THICKNESS + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
with BuildSketch(Plane.XY):
|
||||
SlotOverall(width=POCKET_LENGTH, height=POCKET_WIDTH)
|
||||
extrude(amount=POCKET_DEPTH, mode=Mode.SUBTRACT)
|
||||
|
||||
with BuildSketch(Plane.XY.offset(THICKNESS - POCKET_DEPTH)):
|
||||
SlotOverall(width=POCKET_LENGTH, height=POCKET_WIDTH)
|
||||
extrude(amount=POCKET_DEPTH, mode=Mode.SUBTRACT)
|
||||
|
||||
with BuildSketch(Plane.XY.offset(VIEWER_SLOT_SURFACE_Z - VIEWER_SLOT_BLIND_DEPTH)):
|
||||
with Locations(Location((VIEWER_SLOT_CENTER[0], VIEWER_SLOT_CENTER[1], 0.0))):
|
||||
SlotOverall(
|
||||
width=VIEWER_SLOT_LENGTH,
|
||||
height=VIEWER_SLOT_WIDTH,
|
||||
rotation=VIEWER_SLOT_ROTATION,
|
||||
)
|
||||
extrude(amount=VIEWER_SLOT_BLIND_DEPTH, mode=Mode.SUBTRACT)
|
||||
|
||||
with Locations(
|
||||
Location(
|
||||
(
|
||||
VIEWER_HOLE_CENTER[0],
|
||||
VIEWER_HOLE_CENTER[1],
|
||||
VIEWER_HOLE_SURFACE_Z - VIEWER_HOLE_BLIND_DEPTH,
|
||||
)
|
||||
)
|
||||
):
|
||||
Cylinder(
|
||||
radius=VIEWER_HOLE_DIAMETER / 2.0,
|
||||
height=VIEWER_HOLE_BLIND_DEPTH + VIEWER_HOLE_BOOLEAN_OVERTRAVEL,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
result = rod.part
|
||||
result = fillet(_viewer_edge_e14(result), radius=VIEWER_EDGE_E14_FILLET_RADIUS)
|
||||
result.label = "cad_router_v1_connecting_rod"
|
||||
return result
|
||||
|
Before Width: | Height: | Size: 410 KiB |
@@ -1,106 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "参考图片生成一个8孔圆法兰,中心孔直径20毫米,外径50毫米,厚度4毫米,螺丝孔使用M3;根据 viewer 选中的几何位置添加2x2、直径2毫米、8毫米间距的贯穿孔阵列、一个3毫米贯穿沉头孔,以及一个10x6x1毫米矩形口袋",
|
||||
"route": {
|
||||
"selected_backend": "build123d",
|
||||
"runner_skill": "cad",
|
||||
"project": "text-to-cad",
|
||||
"fallback_order": ["simplecadapi", "cadam"],
|
||||
"workflow_profiles": ["requirement_refinement", "visual_repair", "source_modification"],
|
||||
"downstream_skills": ["cad-viewer"]
|
||||
},
|
||||
"source": {
|
||||
"path": "flange_8x_m3.py",
|
||||
"format": "python",
|
||||
"backend": "build123d"
|
||||
},
|
||||
"artifacts": [
|
||||
{
|
||||
"path": "flange_8x_m3.step",
|
||||
"role": "primary"
|
||||
},
|
||||
{
|
||||
"path": "flange_8x_m3.stl",
|
||||
"role": "secondary"
|
||||
},
|
||||
{
|
||||
"path": ".flange_8x_m3.step.glb",
|
||||
"role": "viewer_mesh_topology"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"outer_diameter_mm": 50.0,
|
||||
"inner_diameter_mm": 20.0,
|
||||
"thickness_mm": 4.0,
|
||||
"bolt_hole_count": 8,
|
||||
"bolt_hole_diameter_mm": 3.4,
|
||||
"bolt_circle_diameter_mm": 40.0,
|
||||
"angular_spacing_deg": 45.0,
|
||||
"viewer_pattern_center_mm": [8.077088362294017, 15.744119598589815],
|
||||
"viewer_pattern_hole_diameter_mm": 2.0,
|
||||
"viewer_pattern_rows": 2,
|
||||
"viewer_pattern_columns": 2,
|
||||
"viewer_pattern_pitch_x_mm": 8.0,
|
||||
"viewer_pattern_pitch_y_mm": 8.0,
|
||||
"viewer_pattern_depth": "through",
|
||||
"viewer_pattern_hole_centers_mm": [
|
||||
[4.077088362294017, 11.744119598589815],
|
||||
[12.077088362294017, 11.744119598589815],
|
||||
[4.077088362294017, 19.744119598589815],
|
||||
[12.077088362294017, 19.744119598589815]
|
||||
],
|
||||
"viewer_countersink_center_mm": [-14.6034432889167, -4.110394299469192],
|
||||
"viewer_countersink_hole_diameter_mm": 3.0,
|
||||
"viewer_countersink_diameter_mm": 6.0,
|
||||
"viewer_countersink_angle_deg": 90.0,
|
||||
"viewer_countersink_depth": "through",
|
||||
"viewer_pocket_center_mm": [6.197199513379157, -14.374353062530322],
|
||||
"viewer_pocket_shape": "rectangle",
|
||||
"viewer_pocket_width_mm": 10.0,
|
||||
"viewer_pocket_height_mm": 6.0,
|
||||
"viewer_pocket_depth_mm": 1.0,
|
||||
"viewer_pocket_bottom_z_mm": 3.0
|
||||
},
|
||||
"assumptions": [
|
||||
"M3螺丝孔按普通间隙通孔处理,孔径采用3.4毫米,不是M3攻丝底孔。",
|
||||
"未指定分度圆,采用40毫米分度圆,以保持孔到外圆约3.3毫米的最小径向边距。",
|
||||
"参考图中的车削纹理作为外观参考,不生成削弱4毫米薄法兰的深槽。",
|
||||
"矩形口袋按 surface_xy 对齐全局 XY,沿选中面法向进入材料,深度1毫米。"
|
||||
],
|
||||
"validation": [
|
||||
{
|
||||
"path": "validation.json",
|
||||
"status": "passed",
|
||||
"checks": {
|
||||
"step_valid": true,
|
||||
"solid_count": 1,
|
||||
"exact_size_mm": [50.0, 50.0, 4.0],
|
||||
"topology_faces": 24,
|
||||
"topology_edges": 62,
|
||||
"m3_clearance_hole_count": 8,
|
||||
"m3_clearance_hole_diameter_mm": 3.4,
|
||||
"viewer_pattern_hole_count": 4,
|
||||
"viewer_pattern_hole_diameter_mm": 2.0,
|
||||
"viewer_countersink_hole_diameter_mm": 3.0,
|
||||
"viewer_countersink_diameter_mm": 6.0,
|
||||
"viewer_countersink_angle_deg": 90.0,
|
||||
"viewer_pocket_bottom_center_mm": [6.197199513379157, -14.374353062530322, 3.0],
|
||||
"viewer_pocket_bottom_size_mm": [10.0, 6.0],
|
||||
"viewer_pocket_depth_mm": 1.0,
|
||||
"viewer_mesh_topology": ".flange_8x_m3.step.glb",
|
||||
"visual_review": "passed_viewer_pocket_top"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "review/viewer_pocket_top_20260724T031341Z.png",
|
||||
"status": "passed",
|
||||
"checks": {
|
||||
"snapshot_camera": "top",
|
||||
"pocket_visible": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"viewer_links": [
|
||||
"http://127.0.0.1:5174/?dir=%2FUsers%2Flk%2FProjects%2FcadSet%2Ftext-to-cad%2Fmodels%2Fcad-router-v1%2Fflange_8x_m3&file=flange_8x_m3.step"
|
||||
]
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
"""Parametric eight-hole circular flange generated with build123d."""
|
||||
|
||||
from math import cos, radians, sin, tan
|
||||
|
||||
from build123d import Align, Box, BuildPart, Cone, Cylinder, Location, Locations, Mode
|
||||
|
||||
|
||||
OUTER_DIAMETER_MM = 50.0
|
||||
INNER_DIAMETER_MM = 20.0
|
||||
THICKNESS_MM = 4.0
|
||||
BOLT_HOLE_COUNT = 8
|
||||
M3_CLEARANCE_DIAMETER_MM = 3.4
|
||||
BOLT_CIRCLE_DIAMETER_MM = 40.0
|
||||
M4_THREAD_SPEC = "M4"
|
||||
M4_TAP_DRILL_DIAMETER_MM = 3.3
|
||||
M4_THREAD_DEPTH_MM = 6.0
|
||||
M4_THREAD_HOLE_CENTER_MM = (-6.104359972902419, -13.137483558259564)
|
||||
M4_THREAD_HOLE_FACE_Z_MM = THICKNESS_MM
|
||||
M4_THREAD_HOLE_DIRECTION = (0.0, 0.0, -1.0)
|
||||
VIEWER_PATTERN_CENTER_MM = (8.077088362294017, 15.744119598589815)
|
||||
VIEWER_PATTERN_HOLE_DIAMETER_MM = 2.0
|
||||
VIEWER_PATTERN_ROWS = 2
|
||||
VIEWER_PATTERN_COLUMNS = 2
|
||||
VIEWER_PATTERN_PITCH_X_MM = 8.0
|
||||
VIEWER_PATTERN_PITCH_Y_MM = 8.0
|
||||
VIEWER_PATTERN_FACE_Z_MM = THICKNESS_MM
|
||||
VIEWER_PATTERN_DIRECTION = (0.0, 0.0, -1.0)
|
||||
VIEWER_COUNTERSINK_CENTER_MM = (-14.6034432889167, -4.110394299469192)
|
||||
VIEWER_COUNTERSINK_HOLE_DIAMETER_MM = 3.0
|
||||
VIEWER_COUNTERSINK_DIAMETER_MM = 6.0
|
||||
VIEWER_COUNTERSINK_ANGLE_DEG = 90.0
|
||||
VIEWER_COUNTERSINK_FACE_Z_MM = THICKNESS_MM
|
||||
VIEWER_COUNTERSINK_DIRECTION = (0.0, 0.0, -1.0)
|
||||
VIEWER_POCKET_CENTER_MM = (6.197199513379157, -14.374353062530322)
|
||||
VIEWER_POCKET_WIDTH_MM = 10.0
|
||||
VIEWER_POCKET_HEIGHT_MM = 6.0
|
||||
VIEWER_POCKET_DEPTH_MM = 1.0
|
||||
VIEWER_POCKET_FACE_Z_MM = THICKNESS_MM
|
||||
VIEWER_POCKET_DIRECTION = (0.0, 0.0, -1.0)
|
||||
|
||||
|
||||
def polar_point(radius: float, angle_degrees: float) -> tuple[float, float]:
|
||||
angle = radians(angle_degrees)
|
||||
return radius * cos(angle), radius * sin(angle)
|
||||
|
||||
|
||||
def gen_step():
|
||||
"""Return one STEP-ready flange solid in millimeters."""
|
||||
with BuildPart() as flange:
|
||||
Cylinder(
|
||||
radius=OUTER_DIAMETER_MM / 2.0,
|
||||
height=THICKNESS_MM,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
with Locations(Location((0.0, 0.0, -1.0))):
|
||||
Cylinder(
|
||||
radius=INNER_DIAMETER_MM / 2.0,
|
||||
height=THICKNESS_MM + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
for index in range(BOLT_HOLE_COUNT):
|
||||
angle_degrees = 360.0 * index / BOLT_HOLE_COUNT
|
||||
x_pos, y_pos = polar_point(BOLT_CIRCLE_DIAMETER_MM / 2.0, angle_degrees)
|
||||
with Locations(Location((x_pos, y_pos, -1.0))):
|
||||
Cylinder(
|
||||
radius=M3_CLEARANCE_DIAMETER_MM / 2.0,
|
||||
height=THICKNESS_MM + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
m4_x_pos, m4_y_pos = M4_THREAD_HOLE_CENTER_MM
|
||||
m4_cut_depth = min(M4_THREAD_DEPTH_MM, THICKNESS_MM)
|
||||
with Locations(Location((m4_x_pos, m4_y_pos, M4_THREAD_HOLE_FACE_Z_MM - m4_cut_depth))):
|
||||
Cylinder(
|
||||
radius=M4_TAP_DRILL_DIAMETER_MM / 2.0,
|
||||
height=m4_cut_depth + 1.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
pattern_center_x, pattern_center_y = VIEWER_PATTERN_CENTER_MM
|
||||
pattern_start_x = pattern_center_x - (VIEWER_PATTERN_COLUMNS - 1) * VIEWER_PATTERN_PITCH_X_MM / 2.0
|
||||
pattern_start_y = pattern_center_y - (VIEWER_PATTERN_ROWS - 1) * VIEWER_PATTERN_PITCH_Y_MM / 2.0
|
||||
for row_index in range(VIEWER_PATTERN_ROWS):
|
||||
for column_index in range(VIEWER_PATTERN_COLUMNS):
|
||||
hole_x = pattern_start_x + column_index * VIEWER_PATTERN_PITCH_X_MM
|
||||
hole_y = pattern_start_y + row_index * VIEWER_PATTERN_PITCH_Y_MM
|
||||
with Locations(Location((hole_x, hole_y, -1.0))):
|
||||
Cylinder(
|
||||
radius=VIEWER_PATTERN_HOLE_DIAMETER_MM / 2.0,
|
||||
height=THICKNESS_MM + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
countersink_x, countersink_y = VIEWER_COUNTERSINK_CENTER_MM
|
||||
countersink_radius = VIEWER_COUNTERSINK_DIAMETER_MM / 2.0
|
||||
countersink_through_radius = VIEWER_COUNTERSINK_HOLE_DIAMETER_MM / 2.0
|
||||
countersink_depth = (
|
||||
countersink_radius - countersink_through_radius
|
||||
) / tan(radians(VIEWER_COUNTERSINK_ANGLE_DEG / 2.0))
|
||||
with Locations(Location((countersink_x, countersink_y, -1.0))):
|
||||
Cylinder(
|
||||
radius=countersink_through_radius,
|
||||
height=THICKNESS_MM + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
with Locations(
|
||||
Location((countersink_x, countersink_y, VIEWER_COUNTERSINK_FACE_Z_MM - countersink_depth))
|
||||
):
|
||||
Cone(
|
||||
countersink_through_radius,
|
||||
countersink_radius,
|
||||
countersink_depth + 0.05,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
pocket_x, pocket_y = VIEWER_POCKET_CENTER_MM
|
||||
with Locations(Location((pocket_x, pocket_y, VIEWER_POCKET_FACE_Z_MM - VIEWER_POCKET_DEPTH_MM))):
|
||||
Box(
|
||||
VIEWER_POCKET_WIDTH_MM,
|
||||
VIEWER_POCKET_HEIGHT_MM,
|
||||
VIEWER_POCKET_DEPTH_MM + 0.05,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
part = flange.part
|
||||
part.label = "flange_8x_m3_clearance_with_m4_tapped_hole_viewer_pattern_countersink_and_pocket"
|
||||
return part
|
||||
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 255 KiB |
|
Before Width: | Height: | Size: 342 KiB |
|
Before Width: | Height: | Size: 113 KiB |
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"input": "models/cad-router-v1/flange_8x_m3/flange_8x_m3.step",
|
||||
"mode": "view",
|
||||
"outputs": [
|
||||
{
|
||||
"path": "models/cad-router-v1/flange_8x_m3/review/iso.png",
|
||||
"camera": "iso"
|
||||
},
|
||||
{
|
||||
"path": "models/cad-router-v1/flange_8x_m3/review/iso_opposite.png",
|
||||
"camera": {
|
||||
"direction": [-1, 1, -0.8]
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "models/cad-router-v1/flange_8x_m3/review/top.png",
|
||||
"camera": "top"
|
||||
},
|
||||
{
|
||||
"path": "models/cad-router-v1/flange_8x_m3/review/front.png",
|
||||
"camera": "front"
|
||||
}
|
||||
],
|
||||
"render": {
|
||||
"viewLabels": true,
|
||||
"padding": 0.12,
|
||||
"sizeProfile": "diagnostic"
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
{
|
||||
"step_valid": true,
|
||||
"solid_count": 1,
|
||||
"exact_size_mm": [50.0, 50.0, 4.0],
|
||||
"topology_counts": {
|
||||
"faces": 24,
|
||||
"edges": 62
|
||||
},
|
||||
"outer_radius_mm": 25.0,
|
||||
"inner_radius_mm": 10.0,
|
||||
"m3_clearance_hole_radius_mm": 1.7,
|
||||
"m3_clearance_hole_count": 8,
|
||||
"bolt_circle_radius_mm": 20.0,
|
||||
"angular_spacing_deg": [45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0],
|
||||
"viewer_edits": {
|
||||
"hole_pattern": {
|
||||
"operation": "add_hole_pattern",
|
||||
"selection_point_model_mm": [8.077088362294017, 15.744119598589815, 4.0],
|
||||
"hole_diameter_mm": 2.0,
|
||||
"rows": 2,
|
||||
"columns": 2,
|
||||
"pitch_x_mm": 8.0,
|
||||
"pitch_y_mm": 8.0,
|
||||
"depth": "through",
|
||||
"hole_centers_mm": [
|
||||
[4.077088362294017, 11.744119598589815, 2.0],
|
||||
[12.077088362294017, 11.744119598589815, 2.0],
|
||||
[4.077088362294017, 19.744119598589815, 2.0],
|
||||
[12.077088362294017, 19.744119598589815, 2.0]
|
||||
],
|
||||
"verified_hole_count": 4,
|
||||
"verified_hole_diameter_mm": 2.0,
|
||||
"verified_through_height_mm": 4.0,
|
||||
"max_center_error_mm": 0.0
|
||||
},
|
||||
"countersink": {
|
||||
"operation": "add_countersink",
|
||||
"selection_point_model_mm": [-14.6034432889167, -4.110394299469192, 4.0],
|
||||
"hole_diameter_mm": 3.0,
|
||||
"countersink_diameter_mm": 6.0,
|
||||
"countersink_angle_deg": 90.0,
|
||||
"countersink_depth_mm": 1.5,
|
||||
"depth": "through"
|
||||
},
|
||||
"pocket": {
|
||||
"operation": "add_pocket",
|
||||
"selection_point_model_mm": [6.197199513379157, -14.374353062530322, 4.0],
|
||||
"shape": "rectangle",
|
||||
"width_mm": 10.0,
|
||||
"height_mm": 6.0,
|
||||
"depth_mm": 1.0,
|
||||
"bottom_z_mm": 3.0,
|
||||
"verified_bottom_center_mm": [6.197199513379157, -14.374353062530322, 3.0],
|
||||
"verified_bottom_size_mm": [10.0, 6.0],
|
||||
"verified_bottom_face_count": 1
|
||||
}
|
||||
},
|
||||
"viewer_mesh_topology": {
|
||||
"path": ".flange_8x_m3.step.glb",
|
||||
"regenerated": true
|
||||
},
|
||||
"snapshot_review": {
|
||||
"status": "passed",
|
||||
"path": "review/viewer_pocket_top_20260724T031341Z.png",
|
||||
"camera": "top"
|
||||
},
|
||||
"visual_review": "passed_viewer_pocket_top"
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"task": "Generate an image-inferred flanged hub adapter",
|
||||
"backend": "build123d",
|
||||
"source_of_truth": "flanged_hub_adapter.py",
|
||||
"primary_output": "flanged_hub_adapter.step",
|
||||
"secondary_outputs": ["flanged_hub_adapter.stl"],
|
||||
"units": "mm",
|
||||
"assumptions": {
|
||||
"base_diameter": 100.0,
|
||||
"base_thickness": 6.0,
|
||||
"total_height": 58.0,
|
||||
"central_bore_diameter": 24.0,
|
||||
"peripheral_holes": "4 x diameter 5.5 on PCD 82",
|
||||
"counterbored_holes": "2 x diameter 6.5 through, diameter 12.5 counterbore"
|
||||
},
|
||||
"reference": "/var/folders/97/90ckyxns4ndbb96jw9hhs3jw0000gn/T/codex-clipboard-0cc8755c-fb41-449f-b543-808f2fd64cf1.png",
|
||||
"dimension_status": "inferred from image; not suitable for tolerance-critical manufacture without confirmation"
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
"""Image-inferred parametric flanged hub adapter generated with build123d.
|
||||
|
||||
All dimensions are millimetres. The values are intentionally collected as
|
||||
named parameters because the reference image contains no dimensions.
|
||||
"""
|
||||
|
||||
from math import cos, radians, sin
|
||||
|
||||
from build123d import Align, BuildPart, Cone, Cylinder, Location, Locations, Mode
|
||||
|
||||
|
||||
# Base mounting flange.
|
||||
BASE_DIAMETER = 100.0
|
||||
BASE_THICKNESS = 6.0
|
||||
PERIPHERAL_HOLE_COUNT = 4
|
||||
PERIPHERAL_HOLE_DIAMETER = 5.5
|
||||
PERIPHERAL_HOLE_PCD = 82.0
|
||||
PERIPHERAL_HOLE_START_ANGLE = 45.0
|
||||
|
||||
# Raised hub and tapered transition.
|
||||
LOWER_BOSS_DIAMETER = 62.0
|
||||
LOWER_BOSS_HEIGHT = 8.0
|
||||
TAPER_TOP_DIAMETER = 36.0
|
||||
TAPER_HEIGHT = 10.0
|
||||
|
||||
# Hollow upper sleeve.
|
||||
SLEEVE_OUTER_DIAMETER = 36.0
|
||||
SLEEVE_INNER_DIAMETER = 24.0
|
||||
SLEEVE_HEIGHT = 34.0
|
||||
|
||||
# Two opposed counterbored mounting holes in the raised region.
|
||||
COUNTERBORE_HOLE_SPACING = 44.0
|
||||
COUNTERBORE_THROUGH_DIAMETER = 6.5
|
||||
COUNTERBORE_DIAMETER = 12.5
|
||||
COUNTERBORE_FLOOR_Z = 17.0
|
||||
|
||||
|
||||
TOTAL_HEIGHT = BASE_THICKNESS + LOWER_BOSS_HEIGHT + TAPER_HEIGHT + SLEEVE_HEIGHT
|
||||
|
||||
|
||||
def _polar(radius: float, angle_degrees: float) -> tuple[float, float]:
|
||||
angle = radians(angle_degrees)
|
||||
return radius * cos(angle), radius * sin(angle)
|
||||
|
||||
|
||||
def gen_step():
|
||||
"""Return one STEP-ready flanged hub solid."""
|
||||
with BuildPart() as adapter:
|
||||
Cylinder(
|
||||
BASE_DIAMETER / 2.0,
|
||||
BASE_THICKNESS,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
with Locations(Location((0.0, 0.0, BASE_THICKNESS - 0.05))):
|
||||
Cylinder(
|
||||
LOWER_BOSS_DIAMETER / 2.0,
|
||||
LOWER_BOSS_HEIGHT + 0.05,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
taper_z = BASE_THICKNESS + LOWER_BOSS_HEIGHT - 0.05
|
||||
with Locations(Location((0.0, 0.0, taper_z))):
|
||||
Cone(
|
||||
LOWER_BOSS_DIAMETER / 2.0,
|
||||
TAPER_TOP_DIAMETER / 2.0,
|
||||
TAPER_HEIGHT + 0.05,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
sleeve_z = BASE_THICKNESS + LOWER_BOSS_HEIGHT + TAPER_HEIGHT - 0.05
|
||||
with Locations(Location((0.0, 0.0, sleeve_z))):
|
||||
Cylinder(
|
||||
SLEEVE_OUTER_DIAMETER / 2.0,
|
||||
SLEEVE_HEIGHT + 0.05,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
)
|
||||
|
||||
# Continuous central bore.
|
||||
with Locations(Location((0.0, 0.0, -1.0))):
|
||||
Cylinder(
|
||||
SLEEVE_INNER_DIAMETER / 2.0,
|
||||
TOTAL_HEIGHT + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
# Four outer mounting holes, rotated 45 degrees to match the image.
|
||||
for index in range(PERIPHERAL_HOLE_COUNT):
|
||||
angle = PERIPHERAL_HOLE_START_ANGLE + 360.0 * index / PERIPHERAL_HOLE_COUNT
|
||||
x_pos, y_pos = _polar(PERIPHERAL_HOLE_PCD / 2.0, angle)
|
||||
with Locations(Location((x_pos, y_pos, -1.0))):
|
||||
Cylinder(
|
||||
PERIPHERAL_HOLE_DIAMETER / 2.0,
|
||||
BASE_THICKNESS + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
# Opposed through holes with flat-bottom cylindrical counterbores.
|
||||
for x_pos in (-COUNTERBORE_HOLE_SPACING / 2.0, COUNTERBORE_HOLE_SPACING / 2.0):
|
||||
with Locations(Location((x_pos, 0.0, -1.0))):
|
||||
Cylinder(
|
||||
COUNTERBORE_THROUGH_DIAMETER / 2.0,
|
||||
TOTAL_HEIGHT + 2.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
with Locations(Location((x_pos, 0.0, COUNTERBORE_FLOOR_Z))):
|
||||
Cylinder(
|
||||
COUNTERBORE_DIAMETER / 2.0,
|
||||
TOTAL_HEIGHT - COUNTERBORE_FLOOR_Z + 1.0,
|
||||
align=(Align.CENTER, Align.CENTER, Align.MIN),
|
||||
mode=Mode.SUBTRACT,
|
||||
)
|
||||
|
||||
part = adapter.part
|
||||
part.label = "flanged_hub_adapter_v1"
|
||||
return part
|
||||
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 292 KiB |
|
Before Width: | Height: | Size: 294 KiB |
|
Before Width: | Height: | Size: 196 KiB |
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"input": "models/cad-router-v1/flanged_hub_adapter_v1/flanged_hub_adapter.step",
|
||||
"mode": "view",
|
||||
"outputs": [
|
||||
{
|
||||
"path": "models/cad-router-v1/flanged_hub_adapter_v1/review/iso.png",
|
||||
"camera": {"direction": [1, -1, 0.75]}
|
||||
},
|
||||
{
|
||||
"path": "models/cad-router-v1/flanged_hub_adapter_v1/review/iso_opposite.png",
|
||||
"camera": {"direction": [-1, 1, 0.65]}
|
||||
},
|
||||
{
|
||||
"path": "models/cad-router-v1/flanged_hub_adapter_v1/review/top.png",
|
||||
"camera": "top"
|
||||
},
|
||||
{
|
||||
"path": "models/cad-router-v1/flanged_hub_adapter_v1/review/front.png",
|
||||
"camera": "front"
|
||||
}
|
||||
],
|
||||
"render": {
|
||||
"viewLabels": true,
|
||||
"padding": 0.12,
|
||||
"sizeProfile": "diagnostic"
|
||||
},
|
||||
"display": {
|
||||
"mode": "solid",
|
||||
"projection": "orthographic"
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "生成模数2、20齿、12毫米厚、中心孔12毫米的人字齿轮,导出STEP并保留可重放模型图",
|
||||
"route": {
|
||||
"selected_backend": "simplecadapi",
|
||||
"runner_skill": "simplecadapi",
|
||||
"confidence": "high",
|
||||
"fallback_order": [
|
||||
"build123d",
|
||||
"cadam"
|
||||
],
|
||||
"decision_path": "gear-route-decision.json"
|
||||
},
|
||||
"source": {
|
||||
"path": "herringbone_gear_simplecad.py",
|
||||
"format": "python",
|
||||
"backend": "simplecadapi",
|
||||
"replay_model": "herringbone_gear_simplecad.json"
|
||||
},
|
||||
"artifacts": [
|
||||
{
|
||||
"path": "herringbone_gear_simplecad.step",
|
||||
"role": "primary"
|
||||
},
|
||||
{
|
||||
"path": "herringbone_gear_simplecad.stl",
|
||||
"role": "secondary"
|
||||
},
|
||||
{
|
||||
"path": "herringbone_gear_simplecad_20260722T072647Z.png",
|
||||
"role": "verification_snapshot"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"teeth": 20,
|
||||
"module_mm": 2.0,
|
||||
"pressure_angle_deg": 20.0,
|
||||
"helix_angle_deg": 30.0,
|
||||
"height_mm": 12.0,
|
||||
"bore_diameter_mm": 12.0,
|
||||
"backlash_mm": 0.05
|
||||
},
|
||||
"validation": [
|
||||
{
|
||||
"check": "SimpleCAD operation graph nodes",
|
||||
"result": 270,
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"check": "volume cubic millimeters",
|
||||
"result": 13213.684,
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"check": "STEP topology",
|
||||
"result": {
|
||||
"shape_count": 1,
|
||||
"face_count": 963,
|
||||
"edge_count": 2043,
|
||||
"bounds_mm": [
|
||||
43.99775,
|
||||
43.99775,
|
||||
12.0
|
||||
],
|
||||
"warnings": []
|
||||
},
|
||||
"status": "pass"
|
||||
},
|
||||
{
|
||||
"check": "isometric snapshot review",
|
||||
"result": "Twenty double-helical teeth, the center bore, and the herringbone ridge are visibly present.",
|
||||
"status": "pass"
|
||||
}
|
||||
],
|
||||
"assumptions": [
|
||||
"This sample validates backend routing and parametric generation; it is not a rated transmission design.",
|
||||
"Material, heat treatment, profile shift, tolerance class, strength, lubrication, and mating gear checks remain out of scope."
|
||||
],
|
||||
"viewer_links": [
|
||||
"http://127.0.0.1:4178/?dir=%2FUsers%2Fjerry%2Flinkhand%2FCadSet%2Ftext-to-cad%2Fmodels%2Fcad-router-v1&file=herringbone_gear_simplecad.step"
|
||||
]
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "生成模数2、20齿、12毫米厚、中心孔12毫米的人字齿轮,导出STEP并保留可重放模型图",
|
||||
"selected_backend": "simplecadapi",
|
||||
"runner_skill": "simplecadapi",
|
||||
"confidence": "high",
|
||||
"backend_scores": [
|
||||
{
|
||||
"backend": "simplecadapi",
|
||||
"score": 175,
|
||||
"reasons": [
|
||||
"+20 specialist mechanical baseline",
|
||||
"+65 supported standard mechanical family",
|
||||
"+60 replay, semantic graph, or FreeCAD requirement",
|
||||
"+30 OCP STEP export requested"
|
||||
]
|
||||
},
|
||||
{
|
||||
"backend": "build123d",
|
||||
"score": 78,
|
||||
"reasons": [
|
||||
"+35 general STEP-first default",
|
||||
"+8 can model the family generically",
|
||||
"+35 editable STEP requested"
|
||||
]
|
||||
},
|
||||
{
|
||||
"backend": "cadam",
|
||||
"score": -60,
|
||||
"reasons": [
|
||||
"+10 printable CSG baseline",
|
||||
"-70 no native editable STEP output"
|
||||
]
|
||||
}
|
||||
],
|
||||
"fallback_order": [
|
||||
"build123d",
|
||||
"cadam"
|
||||
],
|
||||
"workflow_profiles": [],
|
||||
"downstream_skills": [
|
||||
"cad-viewer"
|
||||
],
|
||||
"requested_outputs": [
|
||||
"step"
|
||||
],
|
||||
"source_of_truth": "SimpleCADAPI Python generator and model JSON",
|
||||
"availability": {
|
||||
"build123d": {
|
||||
"available": true,
|
||||
"probe": "python=/Users/jerry/linkhand/CadSet/text-to-cad/.venv/bin/python"
|
||||
},
|
||||
"simplecadapi": {
|
||||
"available": true,
|
||||
"probe": "python=/Users/jerry/linkhand/CadSet/text-to-cad/.venv/bin/python"
|
||||
},
|
||||
"cadam": {
|
||||
"available": true,
|
||||
"probe": "/Users/jerry/linkhand/CadSet/CADAM"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "生成一个28齿、厚度4毫米的齿轮,并在 viewer 选中的两个面点位置各添加一个2.0毫米贯穿孔;随后根据 viewer 选中的顶面点 f5 添加一个10x6x1毫米矩形口袋",
|
||||
"route": {
|
||||
"selected_backend": "simplecadapi",
|
||||
"runner_skill": "simplecadapi",
|
||||
"project": "SimpleCADAPI",
|
||||
"fallback_order": [
|
||||
"build123d",
|
||||
"cadam"
|
||||
],
|
||||
"workflow_profiles": [],
|
||||
"downstream_skills": [
|
||||
"cad-viewer"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"path": "gear_28t_4mm.py",
|
||||
"format": "python",
|
||||
"backend": "simplecadapi"
|
||||
},
|
||||
"artifacts": [
|
||||
{
|
||||
"path": "gear_28t_4mm.model.json",
|
||||
"role": "replayable_model"
|
||||
},
|
||||
{
|
||||
"path": "gear_28t_4mm.step",
|
||||
"role": "primary"
|
||||
},
|
||||
{
|
||||
"path": "gear_28t_4mm.stl",
|
||||
"role": "secondary"
|
||||
},
|
||||
{
|
||||
"path": ".gear_28t_4mm.step.glb",
|
||||
"role": "viewer_mesh_topology"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"n_teeth": 28,
|
||||
"module_mm": 1.0,
|
||||
"pressure_angle_deg": 20.0,
|
||||
"thickness_mm": 4.0,
|
||||
"bore_diameter_mm": 5.0,
|
||||
"addendum_factor": 1.0,
|
||||
"clearance_factor": 0.25,
|
||||
"backlash_mm": 0.0,
|
||||
"edit_holes": [
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"center_mm": [
|
||||
-2.9189440262073063,
|
||||
5.47686606164935,
|
||||
4.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"center_mm": [
|
||||
7.5974463825483305,
|
||||
-0.8433357012066764,
|
||||
4.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"edit_hole_count": 2,
|
||||
"edit_hole_axis": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"edit_pockets": [
|
||||
{
|
||||
"shape": "rectangle",
|
||||
"width_mm": 10.0,
|
||||
"height_mm": 6.0,
|
||||
"depth_mm": 1.0,
|
||||
"center_mm": [
|
||||
-8.717129036056448,
|
||||
-0.9462437095981322,
|
||||
4.0
|
||||
],
|
||||
"direction": "face_normal",
|
||||
"orientation": "surface_xy",
|
||||
"selected_face": {
|
||||
"reference_id": "f5",
|
||||
"selector": "f5",
|
||||
"face_index": 5428,
|
||||
"row_index": 4,
|
||||
"normal": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"edit_pocket_count": 1
|
||||
},
|
||||
"assumptions": [
|
||||
"未指定模数,V1采用1.0毫米。",
|
||||
"未指定压力角,采用标准20度。",
|
||||
"未指定中心孔,采用5.0毫米通孔。",
|
||||
"未指定齿轮类型,采用直齿渐开线外齿轮。",
|
||||
"viewer 编辑请求未指定孔径,采用2.0毫米贯穿孔作为可编辑默认值。"
|
||||
],
|
||||
"validation": [
|
||||
{
|
||||
"path": "validation.json",
|
||||
"status": "passed",
|
||||
"checks": {
|
||||
"step_valid": true,
|
||||
"solid_count": 1,
|
||||
"bounds_mm": [
|
||||
30.0,
|
||||
30.0,
|
||||
4.0
|
||||
],
|
||||
"pitch_diameter_mm": 28.0,
|
||||
"edit_holes": [
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"center_mm": [
|
||||
-2.9189440262073063,
|
||||
5.47686606164935,
|
||||
4.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"center_mm": [
|
||||
7.5974463825483305,
|
||||
-0.8433357012066764,
|
||||
4.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"edit_hole_count": 2,
|
||||
"edit_pockets": [
|
||||
{
|
||||
"shape": "rectangle",
|
||||
"width_mm": 10.0,
|
||||
"height_mm": 6.0,
|
||||
"depth_mm": 1.0,
|
||||
"center_mm": [
|
||||
-8.717129036056448,
|
||||
-0.9462437095981322,
|
||||
4.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"edit_pocket_count": 1,
|
||||
"faces": 182,
|
||||
"edges": 545,
|
||||
"outside_diameter_mm": 30.0,
|
||||
"volume_mm3": 2167.600632,
|
||||
"viewer_mesh_topology": {
|
||||
"path": ".gear_28t_4mm.step.glb",
|
||||
"status": "regenerated",
|
||||
"face_count": 182,
|
||||
"edge_count": 545,
|
||||
"step_hash": "d07ba4428ce372d7dc65ea31c2c8bf636399f38e40e2bd705029789832825267"
|
||||
},
|
||||
"visual_review": "not_run"
|
||||
}
|
||||
}
|
||||
],
|
||||
"viewer_links": [
|
||||
"http://127.0.0.1:5174/?dir=%2FUsers%2Flk%2FProjects%2FcadSet%2Ftext-to-cad%2Fmodels%2Fcad-router-v1%2Fgear_28t_4mm&file=gear_28t_4mm.step"
|
||||
]
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
"""Parametric 28-tooth spur gear generated with SimpleCADAPI."""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
_PROJECT_ROOT = Path(__file__).resolve().parents[4]
|
||||
_SIMPLECADAPI_SRC = _PROJECT_ROOT / "SimpleCADAPI" / "src"
|
||||
if str(_SIMPLECADAPI_SRC) not in sys.path:
|
||||
sys.path.insert(0, str(_SIMPLECADAPI_SRC))
|
||||
|
||||
import simplecadapi as scad
|
||||
|
||||
|
||||
N_TEETH = 28
|
||||
MODULE_MM = 1.0
|
||||
PRESSURE_ANGLE_DEG = 20.0
|
||||
THICKNESS_MM = 4.0
|
||||
BORE_DIAMETER_MM = 5.0
|
||||
ADDENDUM_FACTOR = 1.0
|
||||
CLEARANCE_FACTOR = 0.25
|
||||
BACKLASH_MM = 0.0
|
||||
VIEWER_SELECTED_EDGE = {
|
||||
"reference_id": "e344",
|
||||
"row_index": 343,
|
||||
"description": "top circular edge of the center bore",
|
||||
}
|
||||
BORE_TOP_CHAMFER_DISTANCE_MM = 3.0
|
||||
EDIT_HOLE_AXIS = (0.0, 0.0, 1.0)
|
||||
EDIT_HOLES = [
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"center_mm": (-2.9189440262073063, 5.47686606164935, THICKNESS_MM),
|
||||
},
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"center_mm": (7.5974463825483305, -0.8433357012066764, THICKNESS_MM),
|
||||
},
|
||||
]
|
||||
EDIT_HOLE_PATTERNS = [
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"rows": 2,
|
||||
"columns": 2,
|
||||
"pitch_x_mm": 8.0,
|
||||
"pitch_y_mm": 8.0,
|
||||
"depth": "through",
|
||||
"direction": "face_normal",
|
||||
"orientation": "surface_xy",
|
||||
"center_mm": (0.24688766006678975, -8.367405492677905, THICKNESS_MM),
|
||||
"selected_face": {
|
||||
"reference_id": "f5",
|
||||
"selector": "f5",
|
||||
"face_index": 2785,
|
||||
"row_index": 4,
|
||||
"normal": (0.0, 0.0, 1.0),
|
||||
},
|
||||
},
|
||||
]
|
||||
EDIT_POCKETS = [
|
||||
{
|
||||
"shape": "rectangle",
|
||||
"width_mm": 10.0,
|
||||
"height_mm": 6.0,
|
||||
"depth_mm": 1.0,
|
||||
"center_mm": (-8.717129036056448, -0.9462437095981322, THICKNESS_MM),
|
||||
"direction": "face_normal",
|
||||
"orientation": "surface_xy",
|
||||
"selected_face": {
|
||||
"reference_id": "f5",
|
||||
"selector": "f5",
|
||||
"face_index": 5428,
|
||||
"row_index": 4,
|
||||
"normal": (0.0, 0.0, 1.0),
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def hole_pattern_centers(pattern):
|
||||
x_center, y_center, z_center = pattern["center_mm"]
|
||||
x_start = x_center - (pattern["columns"] - 1) * pattern["pitch_x_mm"] / 2.0
|
||||
y_start = y_center - (pattern["rows"] - 1) * pattern["pitch_y_mm"] / 2.0
|
||||
return [
|
||||
(
|
||||
x_start + column * pattern["pitch_x_mm"],
|
||||
y_start + row * pattern["pitch_y_mm"],
|
||||
z_center,
|
||||
)
|
||||
for row in range(pattern["rows"])
|
||||
for column in range(pattern["columns"])
|
||||
]
|
||||
|
||||
|
||||
def generate() -> None:
|
||||
output_dir = Path(__file__).resolve().parent
|
||||
|
||||
with scad.GraphSession() as session:
|
||||
gear_blank = scad.std.gear.make_spur_gear_rsolid(
|
||||
n_teeth=N_TEETH,
|
||||
module=MODULE_MM,
|
||||
pressure_angle=PRESSURE_ANGLE_DEG,
|
||||
gear_height=THICKNESS_MM,
|
||||
addendum_factor=ADDENDUM_FACTOR,
|
||||
clearance_factor=CLEARANCE_FACTOR,
|
||||
backlash=BACKLASH_MM,
|
||||
)
|
||||
blank_faces = scad.ql.select(items=gear_blank.get_faces()).all()
|
||||
print("gear_blank_faces", len(blank_faces))
|
||||
|
||||
bore_radius = BORE_DIAMETER_MM / 2.0
|
||||
bore = scad.make_cylinder_rsolid(
|
||||
radius=bore_radius,
|
||||
height=THICKNESS_MM + 2.0,
|
||||
bottom_face_center=(0.0, 0.0, -1.0),
|
||||
axis=(0.0, 0.0, 1.0),
|
||||
)
|
||||
bore_top_chamfer = scad.make_cone_rsolid(
|
||||
bottom_radius=bore_radius,
|
||||
height=BORE_TOP_CHAMFER_DISTANCE_MM,
|
||||
top_radius=bore_radius + BORE_TOP_CHAMFER_DISTANCE_MM,
|
||||
bottom_face_center=(
|
||||
0.0,
|
||||
0.0,
|
||||
THICKNESS_MM - BORE_TOP_CHAMFER_DISTANCE_MM,
|
||||
),
|
||||
axis=(0.0, 0.0, 1.0),
|
||||
)
|
||||
edit_hole_cutters = [
|
||||
scad.make_cylinder_rsolid(
|
||||
radius=hole["diameter_mm"] / 2.0,
|
||||
height=THICKNESS_MM + 2.0,
|
||||
bottom_face_center=(hole["center_mm"][0], hole["center_mm"][1], -1.0),
|
||||
axis=EDIT_HOLE_AXIS,
|
||||
)
|
||||
for hole in EDIT_HOLES
|
||||
]
|
||||
pattern_hole_cutters = [
|
||||
scad.make_cylinder_rsolid(
|
||||
radius=pattern["diameter_mm"] / 2.0,
|
||||
height=THICKNESS_MM + 2.0,
|
||||
bottom_face_center=(center[0], center[1], -1.0),
|
||||
axis=EDIT_HOLE_AXIS,
|
||||
)
|
||||
for pattern in EDIT_HOLE_PATTERNS
|
||||
for center in hole_pattern_centers(pattern)
|
||||
]
|
||||
pocket_cutters = [
|
||||
scad.make_box_rsolid(
|
||||
width=pocket["width_mm"],
|
||||
height=pocket["height_mm"],
|
||||
depth=pocket["depth_mm"] + 0.02,
|
||||
bottom_face_center=(
|
||||
pocket["center_mm"][0],
|
||||
pocket["center_mm"][1],
|
||||
THICKNESS_MM - pocket["depth_mm"],
|
||||
),
|
||||
)
|
||||
for pocket in EDIT_POCKETS
|
||||
]
|
||||
print("viewer_edit_holes", len(edit_hole_cutters))
|
||||
print("viewer_edit_pattern_holes", len(pattern_hole_cutters))
|
||||
print("viewer_edit_pockets", len(pocket_cutters))
|
||||
gear = scad.cut_rsolid(
|
||||
gear_blank,
|
||||
[
|
||||
bore,
|
||||
bore_top_chamfer,
|
||||
*edit_hole_cutters,
|
||||
*pattern_hole_cutters,
|
||||
*pocket_cutters,
|
||||
],
|
||||
skip_non_intersecting=False,
|
||||
)
|
||||
gear = scad.apply_tag(shape=gear, tag="role.power_transmission.gear")
|
||||
gear = scad.apply_tag(shape=gear, tag="feature.viewer_edit_point_hole")
|
||||
gear = scad.apply_tag(shape=gear, tag="feature.viewer_edit_hole_pattern")
|
||||
gear = scad.apply_tag(shape=gear, tag="feature.viewer_edit_rectangular_pocket")
|
||||
gear = scad.apply_tag(shape=gear, tag="feature.viewer_selected_edge_chamfer")
|
||||
final_faces = scad.ql.select(items=gear.get_faces()).all()
|
||||
final_edges = scad.ql.select(items=gear.get_edges()).all()
|
||||
print("final_topology", {"faces": len(final_faces), "edges": len(final_edges)})
|
||||
|
||||
model_json = scad.export_model_json(session=session, indent=2)
|
||||
(output_dir / "gear_28t_4mm.model.json").write_text(model_json, encoding="utf-8")
|
||||
scad.export_step(shapes=gear, filename=str(output_dir / "gear_28t_4mm.step"))
|
||||
scad.export_stl(shapes=gear, filename=str(output_dir / "gear_28t_4mm.stl"))
|
||||
|
||||
pitch_diameter_mm = MODULE_MM * N_TEETH
|
||||
outside_diameter_mm = MODULE_MM * (N_TEETH + 2.0 * ADDENDUM_FACTOR)
|
||||
root_diameter_mm = MODULE_MM * (
|
||||
N_TEETH - 2.0 * (ADDENDUM_FACTOR + CLEARANCE_FACTOR)
|
||||
)
|
||||
validation = {
|
||||
"n_teeth": N_TEETH,
|
||||
"pitch_diameter_mm": pitch_diameter_mm,
|
||||
"outside_diameter_mm": outside_diameter_mm,
|
||||
"root_diameter_mm": root_diameter_mm,
|
||||
"thickness_mm": THICKNESS_MM,
|
||||
"bore_diameter_mm": BORE_DIAMETER_MM,
|
||||
"viewer_selected_edge": VIEWER_SELECTED_EDGE,
|
||||
"bore_top_chamfer_distance_mm": BORE_TOP_CHAMFER_DISTANCE_MM,
|
||||
"bore_top_chamfer_top_diameter_mm": BORE_DIAMETER_MM
|
||||
+ 2.0 * BORE_TOP_CHAMFER_DISTANCE_MM,
|
||||
"edit_holes": [
|
||||
{
|
||||
"diameter_mm": hole["diameter_mm"],
|
||||
"center_mm": list(hole["center_mm"]),
|
||||
}
|
||||
for hole in EDIT_HOLES
|
||||
],
|
||||
"edit_hole_count": len(EDIT_HOLES),
|
||||
"edit_hole_axis": list(EDIT_HOLE_AXIS),
|
||||
"edit_hole_patterns": [
|
||||
{
|
||||
"diameter_mm": pattern["diameter_mm"],
|
||||
"rows": pattern["rows"],
|
||||
"columns": pattern["columns"],
|
||||
"pitch_x_mm": pattern["pitch_x_mm"],
|
||||
"pitch_y_mm": pattern["pitch_y_mm"],
|
||||
"depth": pattern["depth"],
|
||||
"direction": pattern["direction"],
|
||||
"orientation": pattern["orientation"],
|
||||
"center_mm": list(pattern["center_mm"]),
|
||||
"hole_centers_mm": [
|
||||
list(center) for center in hole_pattern_centers(pattern)
|
||||
],
|
||||
"selected_face": {
|
||||
**pattern["selected_face"],
|
||||
"normal": list(pattern["selected_face"]["normal"]),
|
||||
},
|
||||
}
|
||||
for pattern in EDIT_HOLE_PATTERNS
|
||||
],
|
||||
"edit_hole_pattern_count": len(EDIT_HOLE_PATTERNS),
|
||||
"edit_hole_pattern_hole_count": sum(
|
||||
pattern["rows"] * pattern["columns"] for pattern in EDIT_HOLE_PATTERNS
|
||||
),
|
||||
"edit_pockets": [
|
||||
{
|
||||
"shape": pocket["shape"],
|
||||
"width_mm": pocket["width_mm"],
|
||||
"height_mm": pocket["height_mm"],
|
||||
"depth_mm": pocket["depth_mm"],
|
||||
"center_mm": list(pocket["center_mm"]),
|
||||
"direction": pocket["direction"],
|
||||
"orientation": pocket["orientation"],
|
||||
"selected_face": {
|
||||
**pocket["selected_face"],
|
||||
"normal": list(pocket["selected_face"]["normal"]),
|
||||
},
|
||||
}
|
||||
for pocket in EDIT_POCKETS
|
||||
],
|
||||
"edit_pocket_count": len(EDIT_POCKETS),
|
||||
"volume_mm3": round(gear.get_volume(), 6),
|
||||
"faces": len(final_faces),
|
||||
"edges": len(final_edges),
|
||||
"tags": scad.list_tags(shape=gear),
|
||||
"graph_nodes": session.graph.node_count,
|
||||
}
|
||||
(output_dir / "validation.json").write_text(
|
||||
json.dumps(validation, indent=2, ensure_ascii=False) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
print("validation", validation)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate()
|
||||
@@ -1,133 +0,0 @@
|
||||
{
|
||||
"n_teeth": 28,
|
||||
"pitch_diameter_mm": 28.0,
|
||||
"outside_diameter_mm": 30.0,
|
||||
"root_diameter_mm": 25.5,
|
||||
"thickness_mm": 4.0,
|
||||
"bore_diameter_mm": 5.0,
|
||||
"viewer_selected_edge": {
|
||||
"reference_id": "e344",
|
||||
"row_index": 343,
|
||||
"description": "top circular edge of the center bore"
|
||||
},
|
||||
"bore_top_chamfer_distance_mm": 3.0,
|
||||
"bore_top_chamfer_top_diameter_mm": 11.0,
|
||||
"edit_holes": [
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"center_mm": [
|
||||
-2.9189440262073063,
|
||||
5.47686606164935,
|
||||
4.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"center_mm": [
|
||||
7.5974463825483305,
|
||||
-0.8433357012066764,
|
||||
4.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"edit_hole_count": 2,
|
||||
"edit_hole_axis": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"edit_hole_patterns": [
|
||||
{
|
||||
"diameter_mm": 2.0,
|
||||
"rows": 2,
|
||||
"columns": 2,
|
||||
"pitch_x_mm": 8.0,
|
||||
"pitch_y_mm": 8.0,
|
||||
"depth": "through",
|
||||
"direction": "face_normal",
|
||||
"orientation": "surface_xy",
|
||||
"center_mm": [
|
||||
0.24688766006678975,
|
||||
-8.367405492677905,
|
||||
4.0
|
||||
],
|
||||
"hole_centers_mm": [
|
||||
[
|
||||
-3.7531123399332103,
|
||||
-12.367405492677905,
|
||||
4.0
|
||||
],
|
||||
[
|
||||
4.24688766006679,
|
||||
-12.367405492677905,
|
||||
4.0
|
||||
],
|
||||
[
|
||||
-3.7531123399332103,
|
||||
-4.367405492677905,
|
||||
4.0
|
||||
],
|
||||
[
|
||||
4.24688766006679,
|
||||
-4.367405492677905,
|
||||
4.0
|
||||
]
|
||||
],
|
||||
"selected_face": {
|
||||
"reference_id": "f5",
|
||||
"selector": "f5",
|
||||
"face_index": 2785,
|
||||
"row_index": 4,
|
||||
"normal": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"edit_hole_pattern_count": 1,
|
||||
"edit_hole_pattern_hole_count": 4,
|
||||
"edit_pockets": [
|
||||
{
|
||||
"shape": "rectangle",
|
||||
"width_mm": 10.0,
|
||||
"height_mm": 6.0,
|
||||
"depth_mm": 1.0,
|
||||
"center_mm": [
|
||||
-8.717129036056448,
|
||||
-0.9462437095981322,
|
||||
4.0
|
||||
],
|
||||
"direction": "face_normal",
|
||||
"orientation": "surface_xy",
|
||||
"selected_face": {
|
||||
"reference_id": "f5",
|
||||
"selector": "f5",
|
||||
"face_index": 5428,
|
||||
"row_index": 4,
|
||||
"normal": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"edit_pocket_count": 1,
|
||||
"volume_mm3": 2128.275635,
|
||||
"faces": 184,
|
||||
"edges": 557,
|
||||
"tags": [
|
||||
"feature.viewer_edit_hole_pattern",
|
||||
"feature.viewer_edit_point_hole",
|
||||
"feature.viewer_edit_rectangular_pocket",
|
||||
"feature.viewer_selected_edge_chamfer",
|
||||
"role.power_transmission.gear",
|
||||
"sketch.gear_28t_m1.id_0",
|
||||
"sketch_profile.arc_root_0",
|
||||
"solid.boolean.cut",
|
||||
"solid.extrusion"
|
||||
],
|
||||
"graph_nodes": 359
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
"""SimpleCADAPI specialist-backend smoke test for CAD Router V1."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import simplecadapi as scad
|
||||
|
||||
|
||||
N_TEETH = 20
|
||||
MODULE = 2.0
|
||||
PRESSURE_ANGLE = 20.0
|
||||
HELIX_ANGLE = 30.0
|
||||
GEAR_HEIGHT = 12.0
|
||||
BORE_DIAMETER = 12.0
|
||||
|
||||
|
||||
def generate() -> None:
|
||||
output_root = Path(__file__).resolve().parent
|
||||
|
||||
with scad.GraphSession() as session:
|
||||
gear = scad.std.gear.make_herringbone_gear_rsolid(
|
||||
n_teeth=N_TEETH,
|
||||
module=MODULE,
|
||||
pressure_angle=PRESSURE_ANGLE,
|
||||
helix_angle=HELIX_ANGLE,
|
||||
gear_height=GEAR_HEIGHT,
|
||||
addendum_factor=1.0,
|
||||
clearance_factor=0.25,
|
||||
backlash=0.05,
|
||||
)
|
||||
bore = scad.make_cylinder_rsolid(
|
||||
radius=BORE_DIAMETER / 2.0,
|
||||
height=GEAR_HEIGHT + 2.0,
|
||||
bottom_face_center=(0.0, 0.0, -1.0),
|
||||
axis=(0.0, 0.0, 1.0),
|
||||
)
|
||||
gear = scad.cut_rsolid(gear, bore, skip_non_intersecting=False)
|
||||
gear = scad.apply_tag(shape=gear, tag="role.power_transmission.gear")
|
||||
|
||||
model_json = scad.export_model_json(session=session, indent=2)
|
||||
(output_root / "herringbone_gear_simplecad.json").write_text(model_json, encoding="utf-8")
|
||||
scad.export_step(shapes=gear, filename=str(output_root / "herringbone_gear_simplecad.step"))
|
||||
scad.export_stl(shapes=gear, filename=str(output_root / "herringbone_gear_simplecad.stl"))
|
||||
|
||||
print("volume_mm3", round(gear.get_volume(), 3))
|
||||
print("tags", scad.list_tags(shape=gear))
|
||||
print("graph_nodes", session.graph.node_count)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate()
|
||||
|
Before Width: | Height: | Size: 953 KiB |
@@ -1,149 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "把明确提供的 015240.step 转换成可修改的 model-spec.json,并保留原始几何作为精确基体",
|
||||
"route": {
|
||||
"selected_backend": "build123d",
|
||||
"runner_skill": "cad",
|
||||
"project": "text-to-cad",
|
||||
"fallback_order": [
|
||||
"simplecadapi",
|
||||
"cadam"
|
||||
],
|
||||
"workflow_profiles": [],
|
||||
"operation": "modify",
|
||||
"source_mode": "exact_step_base",
|
||||
"modification_mode": "model_spec_parameter_edit"
|
||||
},
|
||||
"source": {
|
||||
"path": "source.step",
|
||||
"format": "step",
|
||||
"backend": "build123d",
|
||||
"sha256": "55aee6a0ad74435503a1e7f108b32c9f403ae9838933e2be6728fb5b2f5cfbd4",
|
||||
"immutable_exact_base": true
|
||||
},
|
||||
"artifacts": [
|
||||
{
|
||||
"path": "model-spec.json",
|
||||
"role": "editable_geometry_contract"
|
||||
},
|
||||
{
|
||||
"path": "imported_015240.step",
|
||||
"role": "primary"
|
||||
},
|
||||
{
|
||||
"path": "imported_015240.stl",
|
||||
"role": "secondary"
|
||||
},
|
||||
{
|
||||
"path": "source.step",
|
||||
"role": "immutable_exact_base"
|
||||
}
|
||||
],
|
||||
"parameters": {},
|
||||
"experience": {
|
||||
"library": "../../../../cad-experience-library/library.json",
|
||||
"context_kind": "generalized_cad_experience_query",
|
||||
"methods_applied": []
|
||||
},
|
||||
"assumptions": [
|
||||
"单位按 STEP 几何和导入工具约定记录为 mm。",
|
||||
"原 STEP 不包含可可靠恢复的原生草图、约束或特征历史;后续修改通过 model-spec.json 的命名参数和修改特征表达。",
|
||||
"“选中面厚度增加”按直接建模语义解释为源面 #f22 沿其 +Z 法向外移 1.0 mm。",
|
||||
"“红圈内的孔缩小”按目标水平板通孔从约 Ø4.8 mm 缩小到 Ø3.6 mm 处理。"
|
||||
],
|
||||
"validation": [
|
||||
{
|
||||
"check": "exact_base_sha256",
|
||||
"passed": true,
|
||||
"value": "55aee6a0ad74435503a1e7f108b32c9f403ae9838933e2be6728fb5b2f5cfbd4"
|
||||
},
|
||||
{
|
||||
"check": "exact_base_geometry_signature",
|
||||
"passed": true,
|
||||
"scope": "immutable_source.step",
|
||||
"size_mm": [
|
||||
26.200001497,
|
||||
18.906424738,
|
||||
28.2
|
||||
],
|
||||
"center_mm": [
|
||||
13.100000748,
|
||||
7.453212369,
|
||||
0.0
|
||||
],
|
||||
"solid_count": 1,
|
||||
"face_count": 31,
|
||||
"edge_count": 87,
|
||||
"volume_mm3": 2400.466496
|
||||
},
|
||||
{
|
||||
"check": "model_spec_parameterized_rebuild",
|
||||
"passed": true,
|
||||
"modified_size_mm": [
|
||||
26.200001497,
|
||||
18.906424738,
|
||||
29.2
|
||||
],
|
||||
"modified_center_mm": [
|
||||
13.100000748,
|
||||
7.453212369,
|
||||
0.5
|
||||
],
|
||||
"solid_count": 1,
|
||||
"volume_mm3": 2476.533646
|
||||
},
|
||||
{
|
||||
"check": "selected_face_f22_extension",
|
||||
"passed": true,
|
||||
"source_plane_z_mm": 14.1,
|
||||
"result_plane_z_mm": 15.1,
|
||||
"extension_mm": 1.0,
|
||||
"result_face": "#f27"
|
||||
},
|
||||
{
|
||||
"check": "circled_hole_resize",
|
||||
"passed": true,
|
||||
"center_mm": [
|
||||
5.9,
|
||||
11.006425,
|
||||
0.0
|
||||
],
|
||||
"axis": "Z",
|
||||
"source_diameter_mm": 4.799996,
|
||||
"result_diameter_mm": 3.6,
|
||||
"result_face": "#f22"
|
||||
},
|
||||
{
|
||||
"check": "source_to_modified_cad_diff",
|
||||
"passed": true,
|
||||
"geometry_changed": true,
|
||||
"size_delta_mm": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"center_delta_mm": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.5
|
||||
]
|
||||
},
|
||||
{
|
||||
"check": "cad_inspect_refs_facts_planes_positioning",
|
||||
"passed": true
|
||||
},
|
||||
{
|
||||
"check": "snapshot_review",
|
||||
"passed": true,
|
||||
"views": [
|
||||
"snapshots/iso_20260723T085707Z.png",
|
||||
"snapshots/iso_opposite_20260723T085707Z.png",
|
||||
"snapshots/top_ortho_20260723T085707Z.png",
|
||||
"snapshots/front_ortho_20260723T085707Z.png"
|
||||
]
|
||||
}
|
||||
],
|
||||
"viewer_links": [
|
||||
"http://127.0.0.1:4179/?dir=%2FUsers%2Fjerry%2Flinkhand%2FCadSet%2Ftext-to-cad%2Fmodels%2Fcad-router-v1%2Fimported_015240&file=imported_015240.step"
|
||||
]
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"model_spec_kind": "parametric_cad_model",
|
||||
"model_id": "imported_015240",
|
||||
"units": "mm",
|
||||
"reconstruction": {
|
||||
"mode": "exact_step_base",
|
||||
"source": {
|
||||
"path": "source.step",
|
||||
"sha256": "55aee6a0ad74435503a1e7f108b32c9f403ae9838933e2be6728fb5b2f5cfbd4",
|
||||
"geometry_signature": {
|
||||
"size_mm": [
|
||||
26.200001497,
|
||||
18.906424738,
|
||||
28.2
|
||||
],
|
||||
"center_mm": [
|
||||
13.100000748,
|
||||
7.453212369,
|
||||
-0.0
|
||||
],
|
||||
"solid_count": 1,
|
||||
"face_count": 31,
|
||||
"edge_count": 87,
|
||||
"volume_mm3": 2400.466496
|
||||
}
|
||||
},
|
||||
"history_recovery": {
|
||||
"status": "not_present_in_step",
|
||||
"contract": "Preserve the imported B-Rep exactly as the immutable base; represent later edits as named parametric modifications."
|
||||
}
|
||||
},
|
||||
"parameters": {
|
||||
"selected_face_extension": {
|
||||
"value": 1.0,
|
||||
"unit": "mm",
|
||||
"role": "outward_offset_of_source_face_f22",
|
||||
"source_face": "#f22",
|
||||
"direction": "+Z"
|
||||
},
|
||||
"target_hole_diameter": {
|
||||
"value": 3.6,
|
||||
"unit": "mm",
|
||||
"role": "diameter_of_circled_horizontal_plate_hole",
|
||||
"source_diameter_mm": 4.799996,
|
||||
"axis": "Z"
|
||||
}
|
||||
},
|
||||
"modifications": [
|
||||
{
|
||||
"id": "extend_selected_face_f22",
|
||||
"operation": "add_box",
|
||||
"source_face": "#f22",
|
||||
"direction": "+Z",
|
||||
"center": [
|
||||
13.1,
|
||||
-1.0,
|
||||
{
|
||||
"parameter": "selected_face_extension",
|
||||
"scale": 0.5,
|
||||
"offset": 14.1
|
||||
}
|
||||
],
|
||||
"size": [
|
||||
22.2,
|
||||
2.0,
|
||||
{
|
||||
"parameter": "selected_face_extension"
|
||||
}
|
||||
],
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": "fill_original_circled_hole",
|
||||
"operation": "add_cylinder",
|
||||
"axis": "z",
|
||||
"center": [
|
||||
5.9,
|
||||
11.006425,
|
||||
0.0
|
||||
],
|
||||
"diameter": 4.799996,
|
||||
"length": 4.0,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": "cut_resized_circled_hole",
|
||||
"operation": "cut_cylinder",
|
||||
"axis": "z",
|
||||
"center": [
|
||||
5.9,
|
||||
11.006425,
|
||||
0.0
|
||||
],
|
||||
"diameter": {
|
||||
"parameter": "target_hole_diameter"
|
||||
},
|
||||
"length": 6.0,
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"outputs": {
|
||||
"step": "imported_015240.step",
|
||||
"stl": "imported_015240.stl"
|
||||
},
|
||||
"validation": {
|
||||
"exact_base_required": true,
|
||||
"geometry_signature_tolerance_mm": 1e-07
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"input": "imported_015240.step",
|
||||
"mode": "view",
|
||||
"outputs": [
|
||||
{
|
||||
"path": "snapshots/iso.png",
|
||||
"camera": "iso"
|
||||
},
|
||||
{
|
||||
"path": "snapshots/iso_opposite.png",
|
||||
"camera": {
|
||||
"direction": [-1, 1, -0.8]
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "snapshots/top_ortho.png",
|
||||
"camera": "top"
|
||||
},
|
||||
{
|
||||
"path": "snapshots/front_ortho.png",
|
||||
"camera": "front"
|
||||
}
|
||||
],
|
||||
"render": {
|
||||
"viewLabels": true,
|
||||
"padding": 0.12,
|
||||
"sizeProfile": "diagnostic"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 299 KiB |
|
Before Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 329 KiB |
|
Before Width: | Height: | Size: 328 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 69 KiB |
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"schema_version": "1.0",
|
||||
"request": "生成中心距120mm、大头孔36mm、小头孔20mm、厚14mm的发动机连杆,导出STEP和STL,后续可以修改参数",
|
||||
"selected_backend": "build123d",
|
||||
"runner_skill": "cad",
|
||||
"confidence": "high",
|
||||
"backend_scores": [
|
||||
{
|
||||
"backend": "build123d",
|
||||
"score": 135,
|
||||
"reasons": [
|
||||
"+35 general STEP-first default",
|
||||
"+35 general mechanical part with direct parametric features",
|
||||
"+25 machining favors STEP-first B-Rep",
|
||||
"+35 editable STEP requested",
|
||||
"+5 secondary mesh export is available"
|
||||
]
|
||||
},
|
||||
{
|
||||
"backend": "simplecadapi",
|
||||
"score": 78,
|
||||
"reasons": [
|
||||
"+20 specialist mechanical baseline",
|
||||
"+10 general OCP modeling is available",
|
||||
"+18 OCP STEP geometry suits machining",
|
||||
"+30 OCP STEP export requested"
|
||||
]
|
||||
},
|
||||
{
|
||||
"backend": "cadam",
|
||||
"score": -73,
|
||||
"reasons": [
|
||||
"+10 printable CSG baseline",
|
||||
"-25 mesh/CSG route is not preferred for machining",
|
||||
"-70 no native editable STEP output",
|
||||
"+12 print mesh requested"
|
||||
]
|
||||
}
|
||||
],
|
||||
"fallback_order": [
|
||||
"simplecadapi",
|
||||
"cadam"
|
||||
],
|
||||
"workflow_profiles": [],
|
||||
"downstream_skills": [
|
||||
"cad-viewer"
|
||||
],
|
||||
"requested_outputs": [
|
||||
"step",
|
||||
"stl"
|
||||
],
|
||||
"source_of_truth": "build123d Python generator",
|
||||
"availability": null
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
"""Approximate long multi-collar shaft inferred from reference 001957.png."""
|
||||
|
||||
from shaft_common import cut_end_bore, cut_side_flat, export_horizontal, stepped_body
|
||||
|
||||
|
||||
SEGMENTS = [
|
||||
(10.0, 34.0), # reduced drive tip
|
||||
(14.0, 218.0), # long shaft
|
||||
(19.0, 18.0), # transition shoulder
|
||||
(30.0, 4.0),
|
||||
(25.0, 7.0),
|
||||
(32.0, 5.0),
|
||||
(25.0, 8.0),
|
||||
(31.0, 5.0),
|
||||
(23.0, 8.0),
|
||||
(14.0, 30.0), # hollow output nose
|
||||
]
|
||||
|
||||
|
||||
def gen_step():
|
||||
body, total = stepped_body(SEGMENTS)
|
||||
body = cut_side_flat(body, diameter=10.0, z_start=27.0, length=7.0, flat_depth=1.4)
|
||||
body = cut_end_bore(body, total, diameter=8.0, depth=18.0)
|
||||
return export_horizontal(body, "shaft_001957_like")
|
||||
@@ -1,126 +0,0 @@
|
||||
"""Approximate long cylindrical pin with a shallow axial end recess."""
|
||||
|
||||
from math import atan2, degrees, hypot, sqrt
|
||||
|
||||
from build123d import Box, Cylinder, Location
|
||||
|
||||
from shaft_common import cut_end_bore, export_horizontal, stepped_body
|
||||
|
||||
|
||||
OUTER_DIAMETER = 18.0
|
||||
LENGTH = 120.0
|
||||
RECESS_DIAMETER = 6.0
|
||||
RECESS_DEPTH = 5.0
|
||||
|
||||
VIEWER_POCKET_CENTER = (50.72611906534796, 1.4055875192234604, 8.886497233823093)
|
||||
VIEWER_POCKET_WIDTH = 2.0
|
||||
VIEWER_POCKET_HEIGHT = 2.0
|
||||
VIEWER_POCKET_DEPTH = 1.0
|
||||
VIEWER_POCKET_OVERSHOOT = 0.2
|
||||
|
||||
CIRCULAR_POCKET_CENTER = (68.62703575804954, 0.06569140145571417, 8.989927422862593)
|
||||
CIRCULAR_POCKET_NORMAL = (0.0, -0.156229, -0.987721)
|
||||
CIRCULAR_POCKET_DIAMETER = 8.0
|
||||
CIRCULAR_POCKET_DEPTH = 1.0
|
||||
CIRCULAR_POCKET_OVERSHOOT = 0.2
|
||||
|
||||
COUNTERBORE_CENTER = (40.48928144002571, -7.833112445247494, 4.424155112072327)
|
||||
COUNTERBORE_NORMAL = (0.000061, -0.039505, -0.999219)
|
||||
COUNTERBORE_HOLE_DIAMETER = 3.0
|
||||
COUNTERBORE_DIAMETER = 6.0
|
||||
COUNTERBORE_DEPTH = 2.0
|
||||
COUNTERBORE_FACE_SELECTOR = {
|
||||
"reference_id": "f1",
|
||||
"face_index": 164,
|
||||
"row_index": 0,
|
||||
}
|
||||
COUNTERBORE_OVERSHOOT = 0.2
|
||||
COUNTERBORE_THROUGH_OVERSHOOT = 2.0
|
||||
|
||||
|
||||
def cut_viewer_rectangular_pocket(body):
|
||||
x_pos, y_pos, z_pos = VIEWER_POCKET_CENTER
|
||||
radial_length = hypot(y_pos, z_pos)
|
||||
normal_y = y_pos / radial_length
|
||||
normal_z = z_pos / radial_length
|
||||
rotation_x = degrees(atan2(-normal_y, normal_z))
|
||||
tool_depth = VIEWER_POCKET_DEPTH + VIEWER_POCKET_OVERSHOOT
|
||||
tool_center_offset = (VIEWER_POCKET_OVERSHOOT - VIEWER_POCKET_DEPTH) / 2.0
|
||||
tool_center = (
|
||||
x_pos,
|
||||
y_pos + normal_y * tool_center_offset,
|
||||
z_pos + normal_z * tool_center_offset,
|
||||
)
|
||||
tool = Location(tool_center, (rotation_x, 0.0, 0.0)) * Box(
|
||||
VIEWER_POCKET_WIDTH,
|
||||
VIEWER_POCKET_HEIGHT,
|
||||
tool_depth,
|
||||
)
|
||||
return body - tool
|
||||
|
||||
|
||||
def cut_viewer_circular_pocket(body):
|
||||
x_pos, y_pos, z_pos = CIRCULAR_POCKET_CENTER
|
||||
normal_x, normal_y, normal_z = CIRCULAR_POCKET_NORMAL
|
||||
normal_length = sqrt(normal_x**2 + normal_y**2 + normal_z**2)
|
||||
normal_y /= normal_length
|
||||
normal_z /= normal_length
|
||||
rotation_x = degrees(atan2(-normal_y, normal_z))
|
||||
tool_depth = CIRCULAR_POCKET_DEPTH + CIRCULAR_POCKET_OVERSHOOT
|
||||
tool_center_offset = (CIRCULAR_POCKET_DEPTH - CIRCULAR_POCKET_OVERSHOOT) / 2.0
|
||||
tool_center = (
|
||||
x_pos,
|
||||
y_pos + normal_y * tool_center_offset,
|
||||
z_pos + normal_z * tool_center_offset,
|
||||
)
|
||||
tool = Location(tool_center, (rotation_x, 0.0, 0.0)) * Cylinder(
|
||||
CIRCULAR_POCKET_DIAMETER / 2.0,
|
||||
tool_depth,
|
||||
)
|
||||
return body - tool
|
||||
|
||||
|
||||
def cut_viewer_counterbore(body):
|
||||
x_pos, y_pos, z_pos = COUNTERBORE_CENTER
|
||||
normal_x, normal_y, normal_z = COUNTERBORE_NORMAL
|
||||
normal_length = sqrt(normal_x**2 + normal_y**2 + normal_z**2)
|
||||
normal_y /= normal_length
|
||||
normal_z /= normal_length
|
||||
rotation_x = degrees(atan2(-normal_y, normal_z))
|
||||
|
||||
through_depth = OUTER_DIAMETER + 4.0
|
||||
through_tool_depth = through_depth + COUNTERBORE_THROUGH_OVERSHOOT
|
||||
through_center_offset = (through_depth - COUNTERBORE_THROUGH_OVERSHOOT) / 2.0
|
||||
through_center = (
|
||||
x_pos,
|
||||
y_pos + normal_y * through_center_offset,
|
||||
z_pos + normal_z * through_center_offset,
|
||||
)
|
||||
through_tool = Location(through_center, (rotation_x, 0.0, 0.0)) * Cylinder(
|
||||
COUNTERBORE_HOLE_DIAMETER / 2.0,
|
||||
through_tool_depth,
|
||||
)
|
||||
|
||||
counterbore_tool_depth = COUNTERBORE_DEPTH + COUNTERBORE_OVERSHOOT
|
||||
counterbore_center_offset = (COUNTERBORE_DEPTH - COUNTERBORE_OVERSHOOT) / 2.0
|
||||
counterbore_center = (
|
||||
x_pos,
|
||||
y_pos + normal_y * counterbore_center_offset,
|
||||
z_pos + normal_z * counterbore_center_offset,
|
||||
)
|
||||
counterbore_tool = Location(counterbore_center, (rotation_x, 0.0, 0.0)) * Cylinder(
|
||||
COUNTERBORE_DIAMETER / 2.0,
|
||||
counterbore_tool_depth,
|
||||
)
|
||||
return body - through_tool - counterbore_tool
|
||||
|
||||
|
||||
def gen_step():
|
||||
body, total = stepped_body([(OUTER_DIAMETER, LENGTH)])
|
||||
body = cut_end_bore(body, total, RECESS_DIAMETER, RECESS_DEPTH)
|
||||
result = export_horizontal(body, "pin_004910_like")
|
||||
result = cut_viewer_rectangular_pocket(result)
|
||||
result = cut_viewer_circular_pocket(result)
|
||||
result = cut_viewer_counterbore(result)
|
||||
result.label = "pin_004910_like"
|
||||
return result
|
||||