Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ import {
type Ref,
} from "stepts"
import { generateComponentMeshes } from "./mesh-generation"
import { mergeExternalStepModels } from "./step-model-merger"
import { normalizeStepNumericExponents } from "./step-text-utils"

export interface CircuitJsonToStepOptions {
/** Board width in mm (optional if pcb_board is present) */
Expand Down Expand Up @@ -500,22 +502,40 @@ export async function circuitJsonToStep(
// Array to hold all solids (board + optional components)
const allSolids: Ref<ManifoldSolidBrep>[] = [solid]

// Generate component mesh if requested
let handledComponentIds = new Set<string>()
let handledPcbComponentIds = new Set<string>()

if (options.includeComponents && options.includeExternalMeshes) {
const mergeResult = await mergeExternalStepModels({
repo,
circuitJson,
boardThickness,
})
handledComponentIds = mergeResult.handledComponentIds
handledPcbComponentIds = mergeResult.handledPcbComponentIds
allSolids.push(...mergeResult.solids)
}

// Generate component mesh fallback if requested
if (options.includeComponents) {
const componentSolids = await generateComponentMeshes({
repo,
circuitJson,
boardThickness,
includeExternalMeshes: options.includeExternalMeshes,
excludeCadComponentIds: handledComponentIds,
excludePcbComponentIds: handledPcbComponentIds,
})
allSolids.push(...componentSolids)
}

// Add presentation/styling for all solids
const styledItems: Ref<StyledItem>[] = []

for (const solidRef of allSolids) {
const color = repo.add(new ColourRgb("", 0.2, 0.6, 0.2))
allSolids.forEach((solidRef, index) => {
const isBoard = index === 0
const [r, g, b] = isBoard ? [0.2, 0.6, 0.2] : [0.75, 0.75, 0.75]
const color = repo.add(new ColourRgb("", r, g, b))
const fillColor = repo.add(new FillAreaStyleColour("", color))
const fillStyle = repo.add(new FillAreaStyle("", [fillColor]))
const surfaceFill = repo.add(new SurfaceStyleFillArea(fillStyle))
Expand All @@ -524,7 +544,7 @@ export async function circuitJsonToStep(
const presStyle = repo.add(new PresentationStyleAssignment([surfaceUsage]))
const styledItem = repo.add(new StyledItem("", [presStyle], solidRef))
styledItems.push(styledItem)
}
})

repo.add(
new MechanicalDesignGeometricPresentationRepresentation(
Expand All @@ -541,5 +561,6 @@ export async function circuitJsonToStep(
repo.add(new ShapeDefinitionRepresentation(productDefShape, shapeRep))

// Generate and return STEP file text
return repo.toPartFile({ name: productName })
const stepText = repo.toPartFile({ name: productName })
return normalizeStepNumericExponents(stepText)
}
25 changes: 24 additions & 1 deletion lib/mesh-generation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export interface MeshGenerationOptions {
boardThickness: number
/** Include external model meshes from model_*_url fields (default: false) */
includeExternalMeshes?: boolean
/** Cad component ids already handled by STEP merging */
excludeCadComponentIds?: Set<string>
/** PCB component ids already handled by STEP merging */
excludePcbComponentIds?: Set<string>
}

/**
Expand Down Expand Up @@ -255,13 +259,32 @@ export async function generateComponentMeshes(
circuitJson,
boardThickness,
includeExternalMeshes = false,
excludeCadComponentIds,
excludePcbComponentIds,
} = options
const solids: Ref<ManifoldSolidBrep>[] = []

try {
// Filter circuit JSON and optionally remove model URLs
const filteredCircuitJson = circuitJson
.filter((e) => e.type !== "pcb_board")
.filter((e) => {
if (e.type === "pcb_board") return false
if (
e.type === "cad_component" &&
e.cad_component_id &&
excludeCadComponentIds?.has(e.cad_component_id)
) {
return false
}
if (
e.type === "pcb_component" &&
e.pcb_component_id &&
excludePcbComponentIds?.has(e.pcb_component_id)
) {
return false
}
return true
})
.map((e) => {
if (!includeExternalMeshes && e.type === "cad_component") {
// Remove model_*_url fields to avoid hanging on external model fetches
Expand Down
Loading