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
116 changes: 116 additions & 0 deletions src/examples/2026/sparkfun-boards.fixture.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import type React from "react"
import { PCBViewer } from "../../PCBViewer"

export const SparkfunBoards: React.FC = () => {

return (
<div style={{ backgroundColor: "black", width: "100%", height: "700px" }}>
<PCBViewer circuitJson={[
{
"type": "pcb_plated_hole",
Comment on lines +6 to +10
"pcb_plated_hole_id": "pcb_plated_hole_0",
"pcb_component_id": "pcb_component_0",
"pcb_port_id": "pcb_port_0",
"outer_diameter": 1.88,
"hole_diameter": 1.016,
"shape": "circle",
"port_hints": [
"unnamed_platedhole1",
"pin1"
],
"x": -8,
"y": 0,
"layers": [
"top",
"bottom"
],
"is_covered_with_solder_mask": false,
"subcircuit_id": "subcircuit_source_group_0",
},
{
"type": "pcb_plated_hole",
"pcb_plated_hole_id": "pcb_plated_hole_5",
"pcb_component_id": "pcb_component_1",
"pcb_port_id": "pcb_port_5",
"outer_diameter": 1.88,
"hole_diameter": 1.016,
"shape": "circle",
"port_hints": [
"unnamed_platedhole6",
"1"
],
"x": 8,
"y": 0,
"layers": [
"top",
"bottom"
],
"is_covered_with_solder_mask": false,
"subcircuit_id": "subcircuit_source_group_0"
},
{
"type": "pcb_trace",
"pcb_trace_id": "source_net_0_0",
"route": [
{
"route_type": "wire",
"x": 8,
"y": 0,
"width": 0.15,
"layer": "bottom",
"start_pcb_port_id": "pcb_port_5"
},
{
"route_type": "wire",
"x": 0,
"y": 0,
"width": 0.15,
"layer": "bottom"
},
{
"route_type": "via",
"x": 0,
"y": 0,
"from_layer": "bottom",
"to_layer": "top"
},
{
"route_type": "wire",
"x": 0,
"y": 0,
"width": 0.15,
"layer": "top"
},
{
"route_type": "wire",
"x": -8,
"y": 0,
"width": 0.15,
"layer": "top",
"end_pcb_port_id": "pcb_port_0"
}
],
"subcircuit_id": "subcircuit_source_group_0",
"source_trace_id": "source_net_0"
},
{
"type": "pcb_via",
"pcb_via_id": "pcb_via_0",
"pcb_trace_id": "source_net_0_0",
"x": 0,
"y": 0,
"hole_diameter": 0.2,
"outer_diameter": 0.3,
"layers": [
"bottom",
"top"
],
"from_layer": "bottom",
"to_layer": "top"
}
]} />
</div>
)
}

export default SparkfunBoards
49 changes: 33 additions & 16 deletions src/lib/draw-pcb-trace.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AnyCircuitElement, PcbRenderLayer } from "circuit-json"
import type { AnyCircuitElement, PcbRenderLayer, PcbTrace } from "circuit-json"
import {
CircuitToCanvasDrawer,
DEFAULT_PCB_COLOR_MAP,
Expand All @@ -25,7 +25,7 @@ const HOVER_COLOR_MAP: PcbColorMap = {
},
}

export function isPcbTrace(element: AnyCircuitElement) {
export function isPcbTrace(element: AnyCircuitElement): element is PcbTrace {
return element.type === "pcb_trace"
}

Expand All @@ -34,6 +34,25 @@ const normalizeCopperLayers = (layers: PcbRenderLayer[]) =>
layer.endsWith("_copper") ? layer.replace("_copper", "") : layer,
)

const filterTraceByLayers = (
trace: PcbTrace,
targetLayers: Set<string>,
): PcbTrace | null => {
const filteredRoute = trace.route.filter(
(segment) =>
segment.route_type === "wire" &&
"layer" in segment &&
targetLayers.has(segment.layer),
)

if (filteredRoute.length === 0) return null

return {
...trace,
route: filteredRoute,
}
Comment on lines +41 to +53
}

export function drawPcbTraceElementsForLayer({
canvas,
elements,
Expand All @@ -48,16 +67,11 @@ export function drawPcbTraceElementsForLayer({
primitives?: Primitive[]
}) {
const targetLayers = new Set(normalizeCopperLayers(layers))

const traceElements = elements
.filter(isPcbTrace)
.filter((element) =>
element.route.some(
(segment) =>
segment.route_type === "wire" &&
"layer" in segment &&
targetLayers.has(segment.layer),
),
)
.map((trace) => filterTraceByLayers(trace, targetLayers))
.filter((trace): trace is PcbTrace => trace !== null)

if (traceElements.length === 0) return

Expand All @@ -73,12 +87,15 @@ export function drawPcbTraceElementsForLayer({
}
}

const highlightedElements = traceElements.filter((element) =>
highlightedElementIds.has(element.pcb_trace_id),
)
const nonHighlightedElements = traceElements.filter(
(element) => !highlightedElementIds.has(element.pcb_trace_id),
)
const highlightedElements: PcbTrace[] = []
const nonHighlightedElements: PcbTrace[] = []
for (const element of traceElements) {
if (highlightedElementIds.has(element.pcb_trace_id)) {
highlightedElements.push(element)
} else {
nonHighlightedElements.push(element)
}
}

if (nonHighlightedElements.length > 0) {
const drawer = new CircuitToCanvasDrawer(canvas)
Expand Down
Loading