@tscircuit/core 0.0.2004 → 0.0.2006

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@ import { symbols, SchSymbol, BaseSymbolName } from 'schematic-symbols';
12
12
  import { CircuitJsonUtilObjects } from '@tscircuit/circuit-json-util';
13
13
  import { Matrix } from 'transformation-matrix';
14
14
  import { BusLanesSolver } from '@tscircuit/bus-lanes-solver';
15
- import { AutoroutingPipelineSolver, AssignableAutoroutingPipeline2, AssignableAutoroutingPipeline3, AutoroutingPipeline1_OriginalUnravel, AutoroutingPipelineSolver3_HgPortPointPathing, AutoroutingPipelineSolver4, AutoroutingPipelineSolver5, AutoroutingPipelineSolver8, AutoroutingPipelineSolver9_PreloadedTraceGraph, AutoroutingPipelineSolver9_Networked, AutoroutingPipelineSolver11_Simplification, SimpleRouteJson as SimpleRouteJson$1, SimplifiedPcbTrace as SimplifiedPcbTrace$1 } from '@tscircuit/capacity-autorouter';
15
+ import { AutoroutingPipelineSolver, AssignableAutoroutingPipeline2, AssignableAutoroutingPipeline3, AutoroutingPipeline1_OriginalUnravel, AutoroutingPipelineSolver3_HgPortPointPathing, AutoroutingPipelineSolver4, AutoroutingPipelineSolver5, AutoroutingPipelineSolver7_MultiGraph, AutoroutingPipelineSolver8, AutoroutingPipelineSolver9_Networked, AutoroutingPipelineSolver11_Simplification, SimpleRouteJson as SimpleRouteJson$1, SimplifiedPcbTrace as SimplifiedPcbTrace$1 } from '@tscircuit/capacity-autorouter';
16
16
  import { CopperPourPipelineSolver } from '@tscircuit/copper-pour-solver';
17
17
  import { CreateFdmEnclosureSolver, EnclosureApertureInput } from '@tscircuit/create-fdm-enclosure';
18
18
  import { FanoutSolver } from '@tscircuit/fanout-solver';
@@ -36,9 +36,9 @@ declare const SOLVERS: {
36
36
  AutoroutingPipelineSolver3_HgPortPointPathing: typeof AutoroutingPipelineSolver3_HgPortPointPathing;
37
37
  AutoroutingPipelineSolver4: typeof AutoroutingPipelineSolver4;
38
38
  AutoroutingPipelineSolver5: typeof AutoroutingPipelineSolver5;
39
- AutoroutingPipelineSolver7_MultiGraph: typeof AutoroutingPipelineSolver;
39
+ AutoroutingPipelineSolver7_MultiGraph: typeof AutoroutingPipelineSolver7_MultiGraph;
40
40
  AutoroutingPipelineSolver8: typeof AutoroutingPipelineSolver8;
41
- AutoroutingPipelineSolver9_PreloadedTraceGraph: typeof AutoroutingPipelineSolver9_PreloadedTraceGraph;
41
+ AutoroutingPipelineSolver9_PreloadedTraceGraph: typeof AutoroutingPipelineSolver;
42
42
  AutoroutingPipelineSolver9_Networked: typeof AutoroutingPipelineSolver9_Networked;
43
43
  AutoroutingPipelineSolver11_Simplification: typeof AutoroutingPipelineSolver11_Simplification;
44
44
  CopperPourPipelineSolver: typeof CopperPourPipelineSolver;
@@ -381,9 +381,9 @@ interface IIsolatedCircuit {
381
381
  interface IRootCircuit extends IIsolatedCircuit {
382
382
  }
383
383
 
384
- declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "RenderIsolatedSubcircuits", "InflateSubcircuitCircuitJson", "SourceNameDuplicateComponentRemoval", "PcbFootprintStringRender", "FetchPartFootprint", "ResolveFootprintPinLabels", "InitializePortsFromChildren", "CreateNetsFromProps", "AssignFallbackProps", "CreateTracesFromProps", "CreateTracesFromNetLabels", "CreateTraceHintsFromProps", "CreateAutoplacedBreakoutPoints", "SourceGroupRender", "AssignNameToUnnamedComponents", "SourceRender", "CheckRefDesConvention", "SourceComponentPropertyValidation", "SourceParentAttachment", "PortMatching", "OptimizeSelectorCache", "SourceTraceRender", "SourceAddConnectivityMapKey", "SourceDesignRuleChecks", "SimulationRender", "SchematicComponentRender", "SchematicPortRender", "SymbolContainerRender", "SchematicPrimitiveRender", "SchematicSymbolResize", "SchematicComponentSizeCalculation", "SchematicLayout", "SchematicSectionRender", "SchematicTraceRender", "SchematicSheetRender", "SchematicReplaceNetLabelsWithSymbols", "SchematicLabelNetsWithConflictingNames", "PanelBoardLayout", "ValidatePcbCoordinates", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbComponentSizeCalculation", "PcbComponentAnchorAlignment", "PcbCalcPlacementResolution", "PcbLayout", "PcbBoardAutoSize", "PanelLayout", "PcbFlexRender", "PcbAutoplaceBreakoutPoints", "PcbTraceHintRender", "PcbManualTraceRender", "PcbPlacementDesignRuleChecks", "PcbTraceRender", "PcbRouteNetIslands", "PcbCopperPourRender", "PcbViaStitchRender", "PcbCopperPourCleanup", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "PartOrientationAnalysis", "SupplierFootprintMismatchWarning", "SimulationSpiceEngineRender"];
384
+ declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "RenderIsolatedSubcircuits", "InflateSubcircuitCircuitJson", "SourceNameDuplicateComponentRemoval", "PcbFootprintStringRender", "FetchPartFootprint", "ResolveFootprintPinLabels", "InitializePortsFromChildren", "CreateNetsFromProps", "AssignFallbackProps", "CreateTracesFromProps", "CreateTracesFromNetLabels", "CreateTraceHintsFromProps", "CreateAutoplacedBreakoutPoints", "SourceGroupRender", "AssignNameToUnnamedComponents", "SourceRender", "CheckRefDesConvention", "SourceComponentPropertyValidation", "SourceParentAttachment", "PortMatching", "OptimizeSelectorCache", "SourceTraceRender", "SourceAddConnectivityMapKey", "SourceDesignRuleChecks", "SimulationRender", "SchematicComponentRender", "SchematicPortRender", "SymbolContainerRender", "SchematicPrimitiveRender", "SchematicSymbolResize", "SchematicComponentSizeCalculation", "SchematicLayout", "SchematicSectionRender", "SchematicTraceRender", "SchematicSheetRender", "SchematicReplaceNetLabelsWithSymbols", "SchematicLabelNetsWithConflictingNames", "PanelBoardLayout", "ValidatePcbCoordinates", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbComponentSizeCalculation", "PcbComponentAnchorAlignment", "PcbCalcPlacementResolution", "PcbLayout", "PcbBoardAutoSize", "PanelLayout", "PcbFlexRender", "PcbAutoplaceBreakoutPoints", "PcbTraceHintRender", "PcbManualTraceRender", "PcbPlacementDesignRuleChecks", "PcbTraceRender", "PcbRouteNetIslands", "PcbTraceTeardropRender", "PcbCopperPourRender", "PcbViaStitchRender", "PcbCopperPourCleanup", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "PartOrientationAnalysis", "SupplierFootprintMismatchWarning", "SimulationSpiceEngineRender"];
385
385
  type RenderPhase = (typeof orderedRenderPhases)[number];
386
- declare const renderPhaseIndexMap: Map<"ReactSubtreesRender" | "RenderIsolatedSubcircuits" | "InflateSubcircuitCircuitJson" | "SourceNameDuplicateComponentRemoval" | "PcbFootprintStringRender" | "FetchPartFootprint" | "ResolveFootprintPinLabels" | "InitializePortsFromChildren" | "CreateNetsFromProps" | "AssignFallbackProps" | "CreateTracesFromProps" | "CreateTracesFromNetLabels" | "CreateTraceHintsFromProps" | "CreateAutoplacedBreakoutPoints" | "SourceGroupRender" | "AssignNameToUnnamedComponents" | "SourceRender" | "CheckRefDesConvention" | "SourceComponentPropertyValidation" | "SourceParentAttachment" | "PortMatching" | "OptimizeSelectorCache" | "SourceTraceRender" | "SourceAddConnectivityMapKey" | "SourceDesignRuleChecks" | "SimulationRender" | "SchematicComponentRender" | "SchematicPortRender" | "SymbolContainerRender" | "SchematicPrimitiveRender" | "SchematicSymbolResize" | "SchematicComponentSizeCalculation" | "SchematicLayout" | "SchematicSectionRender" | "SchematicTraceRender" | "SchematicSheetRender" | "SchematicReplaceNetLabelsWithSymbols" | "SchematicLabelNetsWithConflictingNames" | "PanelBoardLayout" | "ValidatePcbCoordinates" | "PcbComponentRender" | "PcbPrimitiveRender" | "PcbFootprintLayout" | "PcbPortRender" | "PcbPortAttachment" | "PcbComponentSizeCalculation" | "PcbComponentAnchorAlignment" | "PcbCalcPlacementResolution" | "PcbLayout" | "PcbBoardAutoSize" | "PanelLayout" | "PcbFlexRender" | "PcbAutoplaceBreakoutPoints" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbPlacementDesignRuleChecks" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbCopperPourRender" | "PcbViaStitchRender" | "PcbCopperPourCleanup" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "PartOrientationAnalysis" | "SupplierFootprintMismatchWarning" | "SimulationSpiceEngineRender", number>;
386
+ declare const renderPhaseIndexMap: Map<"ReactSubtreesRender" | "RenderIsolatedSubcircuits" | "InflateSubcircuitCircuitJson" | "SourceNameDuplicateComponentRemoval" | "PcbFootprintStringRender" | "FetchPartFootprint" | "ResolveFootprintPinLabels" | "InitializePortsFromChildren" | "CreateNetsFromProps" | "AssignFallbackProps" | "CreateTracesFromProps" | "CreateTracesFromNetLabels" | "CreateTraceHintsFromProps" | "CreateAutoplacedBreakoutPoints" | "SourceGroupRender" | "AssignNameToUnnamedComponents" | "SourceRender" | "CheckRefDesConvention" | "SourceComponentPropertyValidation" | "SourceParentAttachment" | "PortMatching" | "OptimizeSelectorCache" | "SourceTraceRender" | "SourceAddConnectivityMapKey" | "SourceDesignRuleChecks" | "SimulationRender" | "SchematicComponentRender" | "SchematicPortRender" | "SymbolContainerRender" | "SchematicPrimitiveRender" | "SchematicSymbolResize" | "SchematicComponentSizeCalculation" | "SchematicLayout" | "SchematicSectionRender" | "SchematicTraceRender" | "SchematicSheetRender" | "SchematicReplaceNetLabelsWithSymbols" | "SchematicLabelNetsWithConflictingNames" | "PanelBoardLayout" | "ValidatePcbCoordinates" | "PcbComponentRender" | "PcbPrimitiveRender" | "PcbFootprintLayout" | "PcbPortRender" | "PcbPortAttachment" | "PcbComponentSizeCalculation" | "PcbComponentAnchorAlignment" | "PcbCalcPlacementResolution" | "PcbLayout" | "PcbBoardAutoSize" | "PanelLayout" | "PcbFlexRender" | "PcbAutoplaceBreakoutPoints" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbPlacementDesignRuleChecks" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbTraceTeardropRender" | "PcbCopperPourRender" | "PcbViaStitchRender" | "PcbCopperPourCleanup" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "PartOrientationAnalysis" | "SupplierFootprintMismatchWarning" | "SimulationSpiceEngineRender", number>;
387
387
  type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
388
388
  type RenderPhaseStates = Record<RenderPhase, {
389
389
  initialized: boolean;
@@ -2038,6 +2038,8 @@ declare class Trace extends PrimitiveComponent<typeof traceProps> implements Tra
2038
2038
  doInitialSourceTraceRender(): void;
2039
2039
  _insertErrorIfTraceIsOutsideBoard(mergedRoute: PcbTraceRoutePoint[], ports: Port[]): void;
2040
2040
  doInitialPcbManualTraceRender(): void;
2041
+ doInitialPcbTraceTeardropRender(): void;
2042
+ updatePcbTraceTeardropRender(): void;
2041
2043
  doInitialPcbTraceRender(): void;
2042
2044
  _doInitialSchematicTraceRenderWithDisplayLabel(): void;
2043
2045
  _isSymbolToChipConnection(): boolean | undefined;
package/dist/index.js CHANGED
@@ -482,6 +482,10 @@ var getRoutePointPositions = (point6) => {
482
482
  // lib/utils/reverse-pcb-trace-route.ts
483
483
  var reversePcbTraceRoute = (route, routeThicknessMode = "constant") => {
484
484
  const reversedRoute = route.slice().reverse().map((point6) => {
485
+ if (point6.route_type === "wire") {
486
+ const { start_width, end_width, width_interpolation_mode, ...wire } = point6;
487
+ return wire;
488
+ }
485
489
  if (point6.route_type !== "through_pad") return { ...point6 };
486
490
  return {
487
491
  ...point6,
@@ -491,39 +495,54 @@ var reversePcbTraceRoute = (route, routeThicknessMode = "constant") => {
491
495
  end_layer: point6.start_layer
492
496
  };
493
497
  });
494
- if (routeThicknessMode === "interpolated") return reversedRoute;
495
- for (let reversedIndex = 0; reversedIndex < reversedRoute.length - 1; reversedIndex++) {
496
- const reversedStart = reversedRoute[reversedIndex];
497
- const reversedEnd = reversedRoute[reversedIndex + 1];
498
- if (reversedStart?.route_type !== "wire" || reversedEnd?.route_type !== "wire" || reversedStart.layer !== reversedEnd.layer) {
499
- continue;
500
- }
501
- const originalSegmentStart = route[route.length - reversedIndex - 2];
502
- if (originalSegmentStart?.route_type === "wire") {
503
- reversedStart.width = originalSegmentStart.width;
504
- }
505
- }
506
- for (let reversedIndex = 0; reversedIndex < reversedRoute.length; reversedIndex++) {
507
- const reversedPoint = reversedRoute[reversedIndex];
508
- if (reversedPoint?.route_type !== "wire") continue;
509
- const nextReversedPoint = reversedRoute[reversedIndex + 1];
510
- if (nextReversedPoint?.route_type === "wire" && nextReversedPoint.layer === reversedPoint.layer) {
511
- continue;
512
- }
513
- let originalRunEndIndex = route.length - reversedIndex - 1;
514
- while (originalRunEndIndex < route.length - 1) {
515
- const originalRunPoint = route[originalRunEndIndex];
516
- const nextOriginalRunPoint = route[originalRunEndIndex + 1];
517
- if (originalRunPoint?.route_type !== "wire" || nextOriginalRunPoint?.route_type !== "wire" || originalRunPoint.layer !== nextOriginalRunPoint.layer) {
518
- break;
498
+ if (routeThicknessMode === "constant") {
499
+ for (let reversedIndex = 0; reversedIndex < reversedRoute.length - 1; reversedIndex++) {
500
+ const reversedStart = reversedRoute[reversedIndex];
501
+ const reversedEnd = reversedRoute[reversedIndex + 1];
502
+ if (reversedStart?.route_type !== "wire" || reversedEnd?.route_type !== "wire" || reversedStart.layer !== reversedEnd.layer) {
503
+ continue;
504
+ }
505
+ const originalSegmentStart = route[route.length - reversedIndex - 2];
506
+ if (originalSegmentStart?.route_type === "wire") {
507
+ reversedStart.width = originalSegmentStart.width;
519
508
  }
520
- originalRunEndIndex++;
521
509
  }
522
- const originalRunEnd = route[originalRunEndIndex];
523
- if (originalRunEnd?.route_type === "wire") {
524
- reversedPoint.width = originalRunEnd.width;
510
+ for (let reversedIndex = 0; reversedIndex < reversedRoute.length; reversedIndex++) {
511
+ const reversedPoint = reversedRoute[reversedIndex];
512
+ if (reversedPoint?.route_type !== "wire") continue;
513
+ const nextReversedPoint = reversedRoute[reversedIndex + 1];
514
+ if (nextReversedPoint?.route_type === "wire" && nextReversedPoint.layer === reversedPoint.layer) {
515
+ continue;
516
+ }
517
+ let originalRunEndIndex = route.length - reversedIndex - 1;
518
+ while (originalRunEndIndex < route.length - 1) {
519
+ const originalRunPoint = route[originalRunEndIndex];
520
+ const nextOriginalRunPoint = route[originalRunEndIndex + 1];
521
+ if (originalRunPoint?.route_type !== "wire" || nextOriginalRunPoint?.route_type !== "wire" || originalRunPoint.layer !== nextOriginalRunPoint.layer) {
522
+ break;
523
+ }
524
+ originalRunEndIndex++;
525
+ }
526
+ const originalRunEnd = route[originalRunEndIndex];
527
+ if (originalRunEnd?.route_type === "wire") {
528
+ reversedPoint.width = originalRunEnd.width;
529
+ }
525
530
  }
526
531
  }
532
+ for (let index = 0; index < route.length - 1; index++) {
533
+ const start = route[index];
534
+ const end = route[index + 1];
535
+ if (start.route_type !== "wire" || !start.width_interpolation_mode) continue;
536
+ if (end.route_type !== "wire" || end.layer !== start.layer) continue;
537
+ const reversedStart = reversedRoute[route.length - index - 2];
538
+ if (reversedStart.route_type !== "wire") continue;
539
+ Object.assign(reversedStart, {
540
+ width: start.end_width,
541
+ start_width: start.end_width,
542
+ end_width: start.start_width,
543
+ width_interpolation_mode: start.width_interpolation_mode
544
+ });
545
+ }
527
546
  return reversedRoute;
528
547
  };
529
548
 
@@ -685,6 +704,7 @@ var orderedRenderPhases = [
685
704
  "PcbPlacementDesignRuleChecks",
686
705
  "PcbTraceRender",
687
706
  "PcbRouteNetIslands",
707
+ "PcbTraceTeardropRender",
688
708
  "PcbCopperPourRender",
689
709
  "PcbViaStitchRender",
690
710
  "PcbCopperPourCleanup",
@@ -734,12 +754,14 @@ var asyncPhaseDependencies = {
734
754
  PcbBoardAutoSize: ["PcbFootprintStringRender", "FetchPartFootprint"],
735
755
  PcbTraceHintRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
736
756
  PcbManualTraceRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
757
+ PcbTraceTeardropRender: ["PcbTraceRender", "PcbRouteNetIslands"],
737
758
  PcbCopperPourRender: [
738
759
  "PcbFootprintStringRender",
739
760
  "FetchPartFootprint",
740
761
  "PcbPlacementDesignRuleChecks",
741
762
  "PcbTraceRender",
742
- "PcbRouteNetIslands"
763
+ "PcbRouteNetIslands",
764
+ "PcbTraceTeardropRender"
743
765
  ],
744
766
  PcbViaStitchRender: [
745
767
  "PcbFootprintStringRender",
@@ -6062,6 +6084,236 @@ function Trace_doInitialPcbManualTraceRender(trace) {
6062
6084
  trace._insertErrorIfTraceIsOutsideBoard(route, ports);
6063
6085
  }
6064
6086
 
6087
+ // lib/utils/autorouting/add-trace-teardrops.ts
6088
+ function addTraceTeardrops(route, contacts) {
6089
+ const result = [];
6090
+ const contactDiameter = (point6) => {
6091
+ let diameter = 0;
6092
+ for (const contact of contacts) {
6093
+ if (contact.layer === point6.layer && Math.hypot(contact.x - point6.x, contact.y - point6.y) < 1e-6)
6094
+ diameter = Math.max(diameter, contact.diameter);
6095
+ }
6096
+ return diameter;
6097
+ };
6098
+ for (let index = 0; index < route.length; index++) {
6099
+ const start = route[index];
6100
+ const end = route[index + 1];
6101
+ if (start.route_type !== "wire" || end?.route_type !== "wire" || start.layer !== end.layer || start.width_interpolation_mode) {
6102
+ result.push(start);
6103
+ continue;
6104
+ }
6105
+ const length8 = Math.hypot(end.x - start.x, end.y - start.y);
6106
+ const startDiameter = contactDiameter(start);
6107
+ const endDiameter = contactDiameter(end);
6108
+ const size = (diameter) => {
6109
+ const width = diameter * 0.8;
6110
+ const taperLength = Math.min(diameter * 1.5, length8 * 0.45);
6111
+ return width > start.width && taperLength > diameter / 2 ? { width, length: taperLength } : void 0;
6112
+ };
6113
+ const startTaper = size(startDiameter);
6114
+ const endTaper = size(endDiameter);
6115
+ if (!startTaper && !endTaper) {
6116
+ result.push(start);
6117
+ continue;
6118
+ }
6119
+ const atDistance = (distance23) => ({
6120
+ route_type: "wire",
6121
+ x: start.x + (end.x - start.x) * distance23 / length8,
6122
+ y: start.y + (end.y - start.y) * distance23 / length8,
6123
+ width: start.width,
6124
+ layer: start.layer
6125
+ });
6126
+ if (startTaper) {
6127
+ result.push({
6128
+ ...start,
6129
+ width: startTaper.width,
6130
+ start_width: startTaper.width,
6131
+ end_width: start.width,
6132
+ width_interpolation_mode: "quadratic"
6133
+ });
6134
+ result.push(atDistance(startTaper.length));
6135
+ } else result.push(start);
6136
+ if (endTaper) {
6137
+ result.push({
6138
+ ...atDistance(length8 - endTaper.length),
6139
+ start_width: start.width,
6140
+ end_width: endTaper.width,
6141
+ width_interpolation_mode: "quadratic"
6142
+ });
6143
+ }
6144
+ }
6145
+ return result;
6146
+ }
6147
+
6148
+ // lib/utils/autorouting/resolve-saved-trace-route-widths.ts
6149
+ function resolveSavedTraceRouteWidths(route) {
6150
+ return route.map((point6, index) => {
6151
+ if (point6.route_type !== "wire" || !point6.width_interpolation_mode)
6152
+ return { ...point6 };
6153
+ const next = route[index + 1];
6154
+ if (next?.route_type !== "wire" || next.layer !== point6.layer || next.x === point6.x && next.y === point6.y) {
6155
+ throw new Error(
6156
+ "Width interpolation requires a distinct next wire point on the same layer"
6157
+ );
6158
+ }
6159
+ return { ...point6, start_width: point6.width, end_width: next.width };
6160
+ });
6161
+ }
6162
+ function getSavedTraceViaContactWidths(route, viaIndex, fallbackWidth) {
6163
+ let before;
6164
+ let after;
6165
+ for (let index = viaIndex - 1; index >= 0; index--) {
6166
+ const point6 = route[index];
6167
+ if (point6.route_type === "wire") {
6168
+ before = point6.width;
6169
+ break;
6170
+ }
6171
+ }
6172
+ for (let index = viaIndex + 1; index < route.length; index++) {
6173
+ const point6 = route[index];
6174
+ if (point6.route_type === "wire") {
6175
+ after = point6.width;
6176
+ break;
6177
+ }
6178
+ }
6179
+ return {
6180
+ fromWidth: before ?? after ?? fallbackWidth,
6181
+ toWidth: after ?? before ?? fallbackWidth
6182
+ };
6183
+ }
6184
+
6185
+ // lib/components/primitive-components/Trace/Trace_doInitialPcbTraceTeardropRender.ts
6186
+ var generatedRoutes = /* @__PURE__ */ new WeakMap();
6187
+ function hasSameGeneratedGeometry(current, generated) {
6188
+ if (current === generated) return true;
6189
+ if (current.length !== generated.length) return false;
6190
+ const geometry = (point6) => {
6191
+ const { is_inside_copper_pour, copper_pour_id, ...rest } = point6;
6192
+ return JSON.stringify(rest);
6193
+ };
6194
+ return current.every(
6195
+ (point6, index) => geometry(point6) === geometry(generated[index])
6196
+ );
6197
+ }
6198
+ function getPadDiameter(pad) {
6199
+ if (pad.shape === "polygon") return 0;
6200
+ if (pad.shape === "circle") return pad.radius * 2;
6201
+ return Math.min(pad.width, pad.height);
6202
+ }
6203
+ function Trace_doInitialPcbTraceTeardropRender(trace) {
6204
+ if (!trace.root || trace.root.pcbDisabled || !trace.source_trace_id) return;
6205
+ const { db } = trace.root;
6206
+ const props = trace._parsedProps;
6207
+ const previous = generatedRoutes.get(trace);
6208
+ for (const [id, routes] of previous ?? []) {
6209
+ const current = db.pcb_trace.get(id);
6210
+ if (current && hasSameGeneratedGeometry(current.route, routes.generated))
6211
+ db.pcb_trace.update(id, { route: routes.original });
6212
+ }
6213
+ generatedRoutes.delete(trace);
6214
+ if (!props.pcbTeardrops && !props.pcbTeardropStart && !props.pcbTeardropEnd)
6215
+ return;
6216
+ const connected = trace._findConnectedPorts();
6217
+ if (!connected.allPortsFound) return;
6218
+ const selectors = trace._getTracePortOrNetSelectorListFromProps();
6219
+ const enabledPorts = connected.portsWithSelectors.map(
6220
+ ({ port, selector }) => ({
6221
+ port,
6222
+ enabled: selector === selectors[0] ? props.pcbTeardropStart ?? props.pcbTeardrops ?? false : selector === selectors.at(-1) ? props.pcbTeardropEnd ?? props.pcbTeardrops ?? false : props.pcbTeardrops ?? false
6223
+ })
6224
+ );
6225
+ const padContacts = [];
6226
+ for (const { port, enabled } of enabledPorts) {
6227
+ if (!enabled || !port.pcb_port_id) continue;
6228
+ for (const pad of db.pcb_smtpad.list({ pcb_port_id: port.pcb_port_id })) {
6229
+ if (pad.shape === "polygon") continue;
6230
+ padContacts.push({
6231
+ x: pad.x,
6232
+ y: pad.y,
6233
+ layer: pad.layer,
6234
+ diameter: getPadDiameter(pad)
6235
+ });
6236
+ }
6237
+ for (const hole of db.pcb_plated_hole.list({
6238
+ pcb_port_id: port.pcb_port_id
6239
+ })) {
6240
+ if (hole.shape !== "circle") continue;
6241
+ for (const layer of hole.layers)
6242
+ padContacts.push({
6243
+ x: hole.x,
6244
+ y: hole.y,
6245
+ layer,
6246
+ diameter: hole.outer_diameter
6247
+ });
6248
+ }
6249
+ }
6250
+ const outputs = /* @__PURE__ */ new Map();
6251
+ for (const pcbTrace of db.pcb_trace.list({
6252
+ source_trace_id: trace.source_trace_id
6253
+ })) {
6254
+ const contacts = [...padContacts];
6255
+ for (const via of db.pcb_via.list({
6256
+ pcb_trace_id: pcbTrace.pcb_trace_id
6257
+ })) {
6258
+ const endpoint = enabledPorts.find(({ port }) => {
6259
+ const position = port._getGlobalPcbPositionAfterLayout();
6260
+ return Math.hypot(position.x - via.x, position.y - via.y) < 1e-6;
6261
+ });
6262
+ if (!(endpoint ? endpoint.enabled : props.pcbTeardrops)) continue;
6263
+ for (const layer of via.layers)
6264
+ contacts.push({
6265
+ x: via.x,
6266
+ y: via.y,
6267
+ layer,
6268
+ diameter: via.outer_diameter
6269
+ });
6270
+ }
6271
+ const wireContacts = pcbTrace.route.flatMap(
6272
+ (point6, index) => {
6273
+ if (point6.route_type !== "via" || !contacts.some(
6274
+ (contact) => Math.hypot(contact.x - point6.x, contact.y - point6.y) < 1e-6
6275
+ ))
6276
+ return [point6];
6277
+ const { fromWidth, toWidth } = getSavedTraceViaContactWidths(
6278
+ pcbTrace.route,
6279
+ index,
6280
+ 0
6281
+ );
6282
+ if (!fromWidth || !toWidth) return [point6];
6283
+ const before = pcbTrace.route[index - 1];
6284
+ const after = pcbTrace.route[index + 1];
6285
+ const result = [];
6286
+ if (!(before?.route_type === "wire" && before.x === point6.x && before.y === point6.y && before.layer === point6.from_layer))
6287
+ result.push({
6288
+ route_type: "wire",
6289
+ x: point6.x,
6290
+ y: point6.y,
6291
+ width: fromWidth,
6292
+ layer: point6.from_layer
6293
+ });
6294
+ result.push(point6);
6295
+ if (!(after?.route_type === "wire" && after.x === point6.x && after.y === point6.y && after.layer === point6.to_layer))
6296
+ result.push({
6297
+ route_type: "wire",
6298
+ x: point6.x,
6299
+ y: point6.y,
6300
+ width: toWidth,
6301
+ layer: point6.to_layer
6302
+ });
6303
+ return result;
6304
+ }
6305
+ );
6306
+ const route = addTraceTeardrops(wireContacts, contacts);
6307
+ if (route.length === pcbTrace.route.length) continue;
6308
+ outputs.set(pcbTrace.pcb_trace_id, {
6309
+ original: pcbTrace.route,
6310
+ generated: route
6311
+ });
6312
+ db.pcb_trace.update(pcbTrace.pcb_trace_id, { route });
6313
+ }
6314
+ generatedRoutes.set(trace, outputs);
6315
+ }
6316
+
6065
6317
  // lib/components/primitive-components/Trace/Trace_doInitialPcbTraceRender.ts
6066
6318
  import { MultilayerIjump } from "@tscircuit/infgrid-ijump-astar";
6067
6319
  import "circuit-json";
@@ -7810,6 +8062,12 @@ var Trace = class extends PrimitiveComponent2 {
7810
8062
  doInitialPcbManualTraceRender() {
7811
8063
  Trace_doInitialPcbManualTraceRender(this);
7812
8064
  }
8065
+ doInitialPcbTraceTeardropRender() {
8066
+ Trace_doInitialPcbTraceTeardropRender(this);
8067
+ }
8068
+ updatePcbTraceTeardropRender() {
8069
+ Trace_doInitialPcbTraceTeardropRender(this);
8070
+ }
7813
8071
  doInitialPcbTraceRender() {
7814
8072
  Trace_doInitialPcbTraceRender(this);
7815
8073
  }
@@ -18957,7 +19215,7 @@ function getSavedAutoroutingPhaseTracesFromPaths({
18957
19215
  `Saved phase path "${path.connection}" starts at an endpoint already joined by another path`
18958
19216
  );
18959
19217
  const transform = getSavedPcbTracePathTransform(group, port);
18960
- const route = path.route.map((point6) => ({
19218
+ const route = resolveSavedTraceRouteWidths(path.route).map((point6) => ({
18961
19219
  ...point6,
18962
19220
  ...applyToPoint27(transform, point6)
18963
19221
  }));
@@ -19005,15 +19263,20 @@ function getSavedAutoroutingPhaseTracesFromPaths({
19005
19263
  pointId: `${pcbTraceId}_exit`
19006
19264
  };
19007
19265
  }
19008
- const width = route.find((point6) => point6.route_type === "wire")?.width ?? input.minTraceWidth;
19009
- const routeWithViaContacts = route.flatMap(
19010
- (point6) => point6.route_type === "via" ? [
19266
+ const routeWithViaContacts = route.flatMap((point6, index) => {
19267
+ if (point6.route_type !== "via") return [point6];
19268
+ const { fromWidth, toWidth } = getSavedTraceViaContactWidths(
19269
+ route,
19270
+ index,
19271
+ input.minTraceWidth
19272
+ );
19273
+ return [
19011
19274
  {
19012
19275
  route_type: "wire",
19013
19276
  x: point6.x,
19014
19277
  y: point6.y,
19015
19278
  layer: point6.from_layer,
19016
- width
19279
+ width: fromWidth
19017
19280
  },
19018
19281
  point6,
19019
19282
  {
@@ -19021,17 +19284,22 @@ function getSavedAutoroutingPhaseTracesFromPaths({
19021
19284
  x: point6.x,
19022
19285
  y: point6.y,
19023
19286
  layer: point6.to_layer,
19024
- width
19287
+ width: toWidth
19025
19288
  }
19026
- ] : [point6]
19027
- );
19289
+ ];
19290
+ });
19028
19291
  if (last.route_type === "via") {
19292
+ const { toWidth } = getSavedTraceViaContactWidths(
19293
+ route,
19294
+ route.length - 1,
19295
+ input.minTraceWidth
19296
+ );
19029
19297
  routeWithViaContacts.push({
19030
19298
  route_type: "wire",
19031
19299
  x: last.x,
19032
19300
  y: last.y,
19033
19301
  layer: last.to_layer,
19034
- width
19302
+ width: toWidth
19035
19303
  });
19036
19304
  }
19037
19305
  coveredConnections.add(connection);
@@ -63687,7 +63955,7 @@ function getSavedFanoutTraces(breakout, input) {
63687
63955
  translate14(-localExit.x, -localExit.y)
63688
63956
  );
63689
63957
  const originalExit = applyToPoint33(transform, localExit);
63690
- const route = path.route.map((point6) => {
63958
+ const route = resolveSavedTraceRouteWidths(path.route).map((point6) => {
63691
63959
  const position = applyToPoint33(transform, point6);
63692
63960
  return {
63693
63961
  ...point6,
@@ -63722,21 +63990,30 @@ function getSavedFanoutTraces(breakout, input) {
63722
63990
  throw new Error(
63723
63991
  `Saved fanout path "${path.connection}" does not cover its connection endpoints`
63724
63992
  );
63725
- const width = route.find((point6) => point6.route_type === "wire")?.width ?? input.minTraceWidth;
63993
+ const startContactWidths = getSavedTraceViaContactWidths(
63994
+ route,
63995
+ 0,
63996
+ input.minTraceWidth
63997
+ );
63998
+ const endContactWidths = getSavedTraceViaContactWidths(
63999
+ route,
64000
+ route.length - 1,
64001
+ input.minTraceWidth
64002
+ );
63726
64003
  if (first.route_type === "via") {
63727
64004
  route.splice(1, 0, {
63728
64005
  route_type: "wire",
63729
64006
  x: first.x,
63730
64007
  y: first.y,
63731
64008
  layer: first.to_layer,
63732
- width
64009
+ width: startContactWidths.toWidth
63733
64010
  });
63734
64011
  route.unshift({
63735
64012
  route_type: "wire",
63736
64013
  x: first.x,
63737
64014
  y: first.y,
63738
64015
  layer: first.from_layer,
63739
- width
64016
+ width: startContactWidths.fromWidth
63740
64017
  });
63741
64018
  }
63742
64019
  if (last.route_type === "via") {
@@ -63745,14 +64022,14 @@ function getSavedFanoutTraces(breakout, input) {
63745
64022
  x: last.x,
63746
64023
  y: last.y,
63747
64024
  layer: last.from_layer,
63748
- width
64025
+ width: endContactWidths.fromWidth
63749
64026
  });
63750
64027
  route.push({
63751
64028
  route_type: "wire",
63752
64029
  x: last.x,
63753
64030
  y: last.y,
63754
64031
  layer: last.to_layer,
63755
- width
64032
+ width: endContactWidths.toWidth
63756
64033
  });
63757
64034
  }
63758
64035
  if (last.route_type === "via") {
@@ -63761,7 +64038,7 @@ function getSavedFanoutTraces(breakout, input) {
63761
64038
  x: last.x,
63762
64039
  y: last.y,
63763
64040
  layer: last.to_layer,
63764
- width
64041
+ width: endContactWidths.toWidth
63765
64042
  });
63766
64043
  }
63767
64044
  coveredConnections.add(connection);
@@ -64162,7 +64439,7 @@ function Group_getRoutingPhasePlans(group) {
64162
64439
  var package_default = {
64163
64440
  name: "@tscircuit/core",
64164
64441
  type: "module",
64165
- version: "0.0.2003",
64442
+ version: "0.0.2005",
64166
64443
  types: "dist/index.d.ts",
64167
64444
  main: "dist/index.js",
64168
64445
  module: "dist/index.js",
@@ -64197,11 +64474,11 @@ var package_default = {
64197
64474
  "@tscircuit/alphabet": "0.0.25",
64198
64475
  "@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
64199
64476
  "@tscircuit/bus-lanes-solver": "github:tscircuit/bus-lanes-solver#0bc8d071241b18a3e7465a878881abe4998f6384",
64200
- "@tscircuit/capacity-autorouter": "^0.0.919",
64477
+ "@tscircuit/capacity-autorouter": "^0.0.941",
64201
64478
  "@tscircuit/checks": "^0.0.224",
64202
64479
  "@tscircuit/circuit-json-util": "^0.0.116",
64203
64480
  "@tscircuit/common": "^0.0.20",
64204
- "@tscircuit/copper-pour-solver": "^0.0.57",
64481
+ "@tscircuit/copper-pour-solver": "^0.0.62",
64205
64482
  "@tscircuit/create-fdm-enclosure": "0.0.4",
64206
64483
  "@tscircuit/fanout-solver": "0.0.78",
64207
64484
  "@tscircuit/flex-utils": "https://jscdn.tscircuit.com/@tscircuit/flex-utils/0.0.5.tgz",
@@ -64238,7 +64515,7 @@ var package_default = {
64238
64515
  "circuit-json-to-connectivity-map": "^0.0.30",
64239
64516
  "circuit-json-to-gltf": "^0.0.133",
64240
64517
  "circuit-json-to-spice": "^0.0.45",
64241
- "circuit-to-svg": "^0.0.430",
64518
+ "circuit-to-svg": "^0.0.433",
64242
64519
  concurrently: "^9.1.2",
64243
64520
  "connectivity-map": "^1.0.0",
64244
64521
  debug: "^4.3.6",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.2004",
4
+ "version": "0.0.2006",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -36,11 +36,11 @@
36
36
  "@tscircuit/alphabet": "0.0.25",
37
37
  "@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
38
38
  "@tscircuit/bus-lanes-solver": "github:tscircuit/bus-lanes-solver#0bc8d071241b18a3e7465a878881abe4998f6384",
39
- "@tscircuit/capacity-autorouter": "^0.0.919",
39
+ "@tscircuit/capacity-autorouter": "^0.0.941",
40
40
  "@tscircuit/checks": "^0.0.224",
41
41
  "@tscircuit/circuit-json-util": "^0.0.116",
42
42
  "@tscircuit/common": "^0.0.20",
43
- "@tscircuit/copper-pour-solver": "^0.0.57",
43
+ "@tscircuit/copper-pour-solver": "^0.0.62",
44
44
  "@tscircuit/create-fdm-enclosure": "0.0.4",
45
45
  "@tscircuit/fanout-solver": "0.0.78",
46
46
  "@tscircuit/flex-utils": "https://jscdn.tscircuit.com/@tscircuit/flex-utils/0.0.5.tgz",
@@ -77,7 +77,7 @@
77
77
  "circuit-json-to-connectivity-map": "^0.0.30",
78
78
  "circuit-json-to-gltf": "^0.0.133",
79
79
  "circuit-json-to-spice": "^0.0.45",
80
- "circuit-to-svg": "^0.0.430",
80
+ "circuit-to-svg": "^0.0.433",
81
81
  "concurrently": "^9.1.2",
82
82
  "connectivity-map": "^1.0.0",
83
83
  "debug": "^4.3.6",