@tscircuit/core 0.0.906 → 0.0.908
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.js +127 -363
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -15047,7 +15047,8 @@ var Inductor = class extends NormalComponent3 {
|
|
|
15047
15047
|
const source_component = db.source_component.insert({
|
|
15048
15048
|
name: this.name,
|
|
15049
15049
|
ftype: FTYPE.simple_inductor,
|
|
15050
|
-
inductance: props.inductance,
|
|
15050
|
+
inductance: this.props.inductance,
|
|
15051
|
+
display_inductance: this._getSchematicSymbolDisplayValue(),
|
|
15051
15052
|
supplier_part_numbers: props.supplierPartNumbers,
|
|
15052
15053
|
are_pins_interchangeable: true
|
|
15053
15054
|
});
|
|
@@ -15825,208 +15826,10 @@ import * as Flatten from "@flatten-js/core";
|
|
|
15825
15826
|
var DEFAULT_PANEL_MARGIN = 5;
|
|
15826
15827
|
var DEFAULT_TAB_LENGTH = 5;
|
|
15827
15828
|
var DEFAULT_TAB_WIDTH = 2;
|
|
15828
|
-
|
|
15829
|
-
const r1Left = rect1.center.x - rect1.width / 2;
|
|
15830
|
-
const r1Right = rect1.center.x + rect1.width / 2;
|
|
15831
|
-
const r1Bottom = rect1.center.y - rect1.height / 2;
|
|
15832
|
-
const r1Top = rect1.center.y + rect1.height / 2;
|
|
15833
|
-
const r2Left = rect2.center.x - rect2.width / 2;
|
|
15834
|
-
const r2Right = rect2.center.x + rect2.width / 2;
|
|
15835
|
-
const r2Bottom = rect2.center.y - rect2.height / 2;
|
|
15836
|
-
const r2Top = rect2.center.y + rect2.height / 2;
|
|
15837
|
-
return !(r1Right <= r2Left || r1Left >= r2Right || r1Top <= r2Bottom || r1Bottom >= r2Top);
|
|
15838
|
-
}
|
|
15839
|
-
function pointOverlapsRectangle(point2, radius, rect) {
|
|
15840
|
-
const rectLeft = rect.center.x - rect.width / 2;
|
|
15841
|
-
const rectRight = rect.center.x + rect.width / 2;
|
|
15842
|
-
const rectBottom = rect.center.y - rect.height / 2;
|
|
15843
|
-
const rectTop = rect.center.y + rect.height / 2;
|
|
15844
|
-
const closestX = Math.max(rectLeft, Math.min(point2.x, rectRight));
|
|
15845
|
-
const closestY = Math.max(rectBottom, Math.min(point2.y, rectTop));
|
|
15846
|
-
const distanceX = point2.x - closestX;
|
|
15847
|
-
const distanceY = point2.y - closestY;
|
|
15848
|
-
return distanceX * distanceX + distanceY * distanceY <= radius * radius;
|
|
15849
|
-
}
|
|
15850
|
-
function generateTabsForEdge({
|
|
15851
|
-
board,
|
|
15852
|
-
edge,
|
|
15853
|
-
otherBoards,
|
|
15854
|
-
options
|
|
15855
|
-
}) {
|
|
15856
|
-
const tabs = [];
|
|
15857
|
-
if (!board.width || !board.height) return tabs;
|
|
15858
|
-
const boardLeft = board.center.x - board.width / 2;
|
|
15859
|
-
const boardRight = board.center.x + board.width / 2;
|
|
15860
|
-
const boardBottom = board.center.y - board.height / 2;
|
|
15861
|
-
const boardTop = board.center.y + board.height / 2;
|
|
15862
|
-
let edgeLength;
|
|
15863
|
-
let isHorizontal;
|
|
15864
|
-
let edgeCenter;
|
|
15865
|
-
if (edge === "top" || edge === "bottom") {
|
|
15866
|
-
edgeLength = board.width;
|
|
15867
|
-
isHorizontal = true;
|
|
15868
|
-
edgeCenter = edge === "top" ? boardTop : boardBottom;
|
|
15869
|
-
} else {
|
|
15870
|
-
edgeLength = board.height;
|
|
15871
|
-
isHorizontal = false;
|
|
15872
|
-
edgeCenter = edge === "right" ? boardRight : boardLeft;
|
|
15873
|
-
}
|
|
15874
|
-
const totalTabWidth = options.tabLength;
|
|
15875
|
-
let fixedSpacing = options.boardGap;
|
|
15876
|
-
if (options.mouseBites) {
|
|
15877
|
-
const mouseBiteDiameter = options.tabWidth * 0.45;
|
|
15878
|
-
const mouseBiteSpacing = mouseBiteDiameter * 0.1;
|
|
15879
|
-
const mouseBitesPerGap = Math.max(2, Math.ceil(options.tabLength / 2));
|
|
15880
|
-
const minSpacingForMouseBites = mouseBitesPerGap * mouseBiteDiameter + (mouseBitesPerGap - 1) * mouseBiteSpacing;
|
|
15881
|
-
fixedSpacing = minSpacingForMouseBites * 1.1;
|
|
15882
|
-
}
|
|
15883
|
-
let numTabs = Math.floor(
|
|
15884
|
-
(edgeLength - fixedSpacing) / (totalTabWidth + fixedSpacing)
|
|
15885
|
-
);
|
|
15886
|
-
if (numTabs < 1 && edgeLength >= totalTabWidth) {
|
|
15887
|
-
numTabs = 1;
|
|
15888
|
-
}
|
|
15889
|
-
if (numTabs === 0) return tabs;
|
|
15890
|
-
const actualSpacing = fixedSpacing;
|
|
15891
|
-
const boardStart = -edgeLength / 2;
|
|
15892
|
-
const boardEnd = edgeLength / 2;
|
|
15893
|
-
for (let i = 0; i < numTabs; i++) {
|
|
15894
|
-
const offsetAlongEdge = boardStart + actualSpacing + i * (totalTabWidth + actualSpacing) + totalTabWidth / 2;
|
|
15895
|
-
const isFirstTab = i === 0;
|
|
15896
|
-
const isLastTab = i === numTabs - 1;
|
|
15897
|
-
const isCornerTab = isFirstTab || isLastTab;
|
|
15898
|
-
let axisStart = offsetAlongEdge - totalTabWidth / 2;
|
|
15899
|
-
let axisEnd = offsetAlongEdge + totalTabWidth / 2;
|
|
15900
|
-
if (isCornerTab) {
|
|
15901
|
-
if (isFirstTab) axisStart = boardStart;
|
|
15902
|
-
if (isLastTab) axisEnd = boardEnd;
|
|
15903
|
-
}
|
|
15904
|
-
axisStart = Math.max(axisStart, boardStart);
|
|
15905
|
-
axisEnd = Math.min(axisEnd, boardEnd);
|
|
15906
|
-
if (isCornerTab) {
|
|
15907
|
-
if (isFirstTab) axisStart -= options.tabWidth;
|
|
15908
|
-
if (isLastTab) axisEnd += options.tabWidth;
|
|
15909
|
-
}
|
|
15910
|
-
if (axisEnd <= axisStart) continue;
|
|
15911
|
-
const axisCenterOffset = (axisStart + axisEnd) / 2;
|
|
15912
|
-
const axisLength = axisEnd - axisStart;
|
|
15913
|
-
const crossAxisOffset = edge === "top" || edge === "right" ? options.tabWidth / 2 : -options.tabWidth / 2;
|
|
15914
|
-
const tabCenter = isHorizontal ? {
|
|
15915
|
-
x: board.center.x + axisCenterOffset,
|
|
15916
|
-
y: edgeCenter + crossAxisOffset
|
|
15917
|
-
} : {
|
|
15918
|
-
x: edgeCenter + crossAxisOffset,
|
|
15919
|
-
y: board.center.y + axisCenterOffset
|
|
15920
|
-
};
|
|
15921
|
-
const tabWidth = isHorizontal ? axisLength : options.tabWidth;
|
|
15922
|
-
const tabHeight = isHorizontal ? options.tabWidth : axisLength;
|
|
15923
|
-
const newTab = {
|
|
15924
|
-
center: tabCenter,
|
|
15925
|
-
width: tabWidth,
|
|
15926
|
-
height: tabHeight,
|
|
15927
|
-
boardId: `${board.center.x}_${board.center.y}`
|
|
15928
|
-
};
|
|
15929
|
-
let overlapsBoard = false;
|
|
15930
|
-
for (const otherBoard of otherBoards) {
|
|
15931
|
-
if (!otherBoard.width || !otherBoard.height) continue;
|
|
15932
|
-
const boardRect = {
|
|
15933
|
-
center: otherBoard.center,
|
|
15934
|
-
width: otherBoard.width,
|
|
15935
|
-
height: otherBoard.height
|
|
15936
|
-
};
|
|
15937
|
-
if (rectanglesOverlap(newTab, boardRect)) {
|
|
15938
|
-
overlapsBoard = true;
|
|
15939
|
-
break;
|
|
15940
|
-
}
|
|
15941
|
-
}
|
|
15942
|
-
if (overlapsBoard && !isCornerTab) continue;
|
|
15943
|
-
tabs.push(newTab);
|
|
15944
|
-
}
|
|
15945
|
-
return tabs;
|
|
15946
|
-
}
|
|
15947
|
-
function generateMouseBitesForEdge({
|
|
15948
|
-
board,
|
|
15949
|
-
edge,
|
|
15950
|
-
edgeTabs,
|
|
15951
|
-
allBoards,
|
|
15952
|
-
options
|
|
15953
|
-
}) {
|
|
15954
|
-
const mouseBites = [];
|
|
15955
|
-
if (edgeTabs.length === 0) return mouseBites;
|
|
15956
|
-
if (!board.width || !board.height) return mouseBites;
|
|
15957
|
-
const boardLeft = board.center.x - board.width / 2;
|
|
15958
|
-
const boardRight = board.center.x + board.width / 2;
|
|
15959
|
-
const boardBottom = board.center.y - board.height / 2;
|
|
15960
|
-
const boardTop = board.center.y + board.height / 2;
|
|
15961
|
-
const isHorizontal = edge === "top" || edge === "bottom";
|
|
15962
|
-
const mouseBiteDiameter = options.tabWidth * 0.45;
|
|
15963
|
-
const mouseBiteSpacing = mouseBiteDiameter * 0.1;
|
|
15964
|
-
const mouseBitesPerGap = Math.max(2, Math.ceil(options.tabLength / 2));
|
|
15965
|
-
let mouseBitePosition;
|
|
15966
|
-
const radius = mouseBiteDiameter / 2;
|
|
15967
|
-
if (edge === "top") {
|
|
15968
|
-
mouseBitePosition = boardTop;
|
|
15969
|
-
} else if (edge === "bottom") {
|
|
15970
|
-
mouseBitePosition = boardBottom;
|
|
15971
|
-
} else if (edge === "right") {
|
|
15972
|
-
mouseBitePosition = boardRight;
|
|
15973
|
-
} else {
|
|
15974
|
-
mouseBitePosition = boardLeft;
|
|
15975
|
-
}
|
|
15976
|
-
const sortedTabs = [...edgeTabs].sort((a, b) => {
|
|
15977
|
-
if (isHorizontal) {
|
|
15978
|
-
return a.center.x - b.center.x;
|
|
15979
|
-
} else {
|
|
15980
|
-
return a.center.y - b.center.y;
|
|
15981
|
-
}
|
|
15982
|
-
});
|
|
15983
|
-
for (let i = 0; i < sortedTabs.length - 1; i++) {
|
|
15984
|
-
const tab1 = sortedTabs[i];
|
|
15985
|
-
const tab2 = sortedTabs[i + 1];
|
|
15986
|
-
let gapStart;
|
|
15987
|
-
let gapEnd;
|
|
15988
|
-
if (isHorizontal) {
|
|
15989
|
-
gapStart = tab1.center.x + tab1.width / 2;
|
|
15990
|
-
gapEnd = tab2.center.x - tab2.width / 2;
|
|
15991
|
-
} else {
|
|
15992
|
-
gapStart = tab1.center.y + tab1.height / 2;
|
|
15993
|
-
gapEnd = tab2.center.y - tab2.height / 2;
|
|
15994
|
-
}
|
|
15995
|
-
const gapLength = gapEnd - gapStart;
|
|
15996
|
-
const totalMouseBiteWidth = mouseBitesPerGap * mouseBiteDiameter;
|
|
15997
|
-
const totalSpacing = (mouseBitesPerGap - 1) * mouseBiteSpacing;
|
|
15998
|
-
if (gapLength < totalMouseBiteWidth + totalSpacing) continue;
|
|
15999
|
-
const gapCenter = (gapStart + gapEnd) / 2;
|
|
16000
|
-
for (let j = 0; j < mouseBitesPerGap; j++) {
|
|
16001
|
-
const posOffset = (j - (mouseBitesPerGap - 1) / 2) * (mouseBiteDiameter + mouseBiteSpacing);
|
|
16002
|
-
const newMouseBite = isHorizontal ? { x: gapCenter + posOffset, y: mouseBitePosition } : { x: mouseBitePosition, y: gapCenter + posOffset };
|
|
16003
|
-
const radius2 = mouseBiteDiameter / 2;
|
|
16004
|
-
let overlapsBoard = false;
|
|
16005
|
-
for (const otherBoard of allBoards) {
|
|
16006
|
-
if (!otherBoard.width || !otherBoard.height) continue;
|
|
16007
|
-
const boardRect = {
|
|
16008
|
-
center: otherBoard.center,
|
|
16009
|
-
width: otherBoard.width,
|
|
16010
|
-
height: otherBoard.height
|
|
16011
|
-
};
|
|
16012
|
-
if (pointOverlapsRectangle(newMouseBite, radius2, boardRect)) {
|
|
16013
|
-
overlapsBoard = true;
|
|
16014
|
-
break;
|
|
16015
|
-
}
|
|
16016
|
-
}
|
|
16017
|
-
if (overlapsBoard) continue;
|
|
16018
|
-
mouseBites.push(newMouseBite);
|
|
16019
|
-
}
|
|
16020
|
-
}
|
|
16021
|
-
return mouseBites;
|
|
16022
|
-
}
|
|
16023
|
-
var generatePanelTabsAndMouseBitesForOutlines = (outline, otherBoards, options) => {
|
|
15829
|
+
var generateCutoutsAndMousebitesForOutline = (outline, options) => {
|
|
16024
15830
|
const {
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
// along edge
|
|
16028
|
-
tabWidth,
|
|
16029
|
-
// extrusion
|
|
15831
|
+
gapLength,
|
|
15832
|
+
cutoutWidth,
|
|
16030
15833
|
mouseBites,
|
|
16031
15834
|
mouseBiteHoleDiameter,
|
|
16032
15835
|
mouseBiteHoleSpacing
|
|
@@ -16039,181 +15842,142 @@ var generatePanelTabsAndMouseBitesForOutlines = (outline, otherBoards, options)
|
|
|
16039
15842
|
const outlinePolygon = new Flatten.Polygon(
|
|
16040
15843
|
outline.map((p) => Flatten.point(p.x, p.y))
|
|
16041
15844
|
);
|
|
16042
|
-
|
|
16043
|
-
|
|
16044
|
-
|
|
16045
|
-
|
|
16046
|
-
|
|
16047
|
-
|
|
16048
|
-
|
|
16049
|
-
|
|
16050
|
-
for (let i = 0; i < outline.length; i++) {
|
|
16051
|
-
const p1 = outline[i];
|
|
16052
|
-
const p2 = outline[(i + 1) % outline.length];
|
|
16053
|
-
const segmentVector = Flatten.vector(p2.x - p1.x, p2.y - p1.y);
|
|
16054
|
-
const segmentLength = segmentVector.length;
|
|
16055
|
-
const physicalTabLength = boardGap;
|
|
16056
|
-
const cutoutLength = tabLength;
|
|
16057
|
-
if (segmentLength < physicalTabLength) continue;
|
|
16058
|
-
const segmentDirVec = segmentVector.normalize();
|
|
16059
|
-
const isHorizontal = Math.abs(segmentVector.y) < 1e-9;
|
|
16060
|
-
const isVertical = Math.abs(segmentVector.x) < 1e-9;
|
|
16061
|
-
const isAxisAligned = isHorizontal || isVertical;
|
|
16062
|
-
let normalVec = segmentDirVec.rotate(Math.PI / 2);
|
|
16063
|
-
const midPoint = Flatten.point(p1.x, p1.y).translate(
|
|
16064
|
-
segmentDirVec.multiply(segmentLength / 2)
|
|
15845
|
+
let is_ccw;
|
|
15846
|
+
if (outline.length > 2) {
|
|
15847
|
+
const p0 = Flatten.point(outline[0].x, outline[0].y);
|
|
15848
|
+
const p1 = Flatten.point(outline[1].x, outline[1].y);
|
|
15849
|
+
const segmentDir = Flatten.vector(p0, p1).normalize();
|
|
15850
|
+
const normalToLeft = segmentDir.rotate(Math.PI / 2);
|
|
15851
|
+
const midPoint = p0.translate(
|
|
15852
|
+
segmentDir.multiply(Flatten.segment(p0, p1).length / 2)
|
|
16065
15853
|
);
|
|
16066
|
-
const
|
|
16067
|
-
|
|
15854
|
+
const testPoint = midPoint.translate(normalToLeft.multiply(0.01));
|
|
15855
|
+
is_ccw = outlinePolygon.contains(testPoint);
|
|
15856
|
+
} else {
|
|
15857
|
+
is_ccw = outlinePolygon.area() > 0;
|
|
15858
|
+
}
|
|
15859
|
+
for (let i = 0; i < outline.length; i++) {
|
|
15860
|
+
const p1_ = outline[i];
|
|
15861
|
+
const p2_ = outline[(i + 1) % outline.length];
|
|
15862
|
+
if (!p1_ || !p2_) continue;
|
|
15863
|
+
const p1 = Flatten.point(p1_.x, p1_.y);
|
|
15864
|
+
const p2 = Flatten.point(p2_.x, p2_.y);
|
|
15865
|
+
const segment2 = Flatten.segment(p1, p2);
|
|
15866
|
+
const segmentLength = segment2.length;
|
|
15867
|
+
if (segmentLength < 1e-6) continue;
|
|
15868
|
+
const segmentVec = Flatten.vector(p1, p2);
|
|
15869
|
+
const segmentDir = segmentVec.normalize();
|
|
15870
|
+
let normalVec = segmentDir.rotate(Math.PI / 2);
|
|
15871
|
+
const midPoint = segment2.middle();
|
|
15872
|
+
const testPoint = midPoint.translate(normalVec.multiply(0.01));
|
|
15873
|
+
if (outlinePolygon.contains(testPoint)) {
|
|
16068
15874
|
normalVec = normalVec.multiply(-1);
|
|
16069
15875
|
}
|
|
16070
|
-
const
|
|
16071
|
-
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
|
|
16075
|
-
|
|
16076
|
-
|
|
16077
|
-
break;
|
|
16078
|
-
}
|
|
16079
|
-
}
|
|
16080
|
-
if (!isExterior) continue;
|
|
16081
|
-
const numTabs = Math.max(
|
|
16082
|
-
1,
|
|
16083
|
-
Math.floor(segmentLength / (physicalTabLength + cutoutLength))
|
|
16084
|
-
);
|
|
16085
|
-
const totalContentLength = numTabs * physicalTabLength;
|
|
16086
|
-
const totalGapLength = segmentLength - totalContentLength;
|
|
16087
|
-
const gapSize = totalGapLength / (numTabs + 1);
|
|
16088
|
-
if (gapSize < 0) continue;
|
|
16089
|
-
const tabsOnSegment = [];
|
|
16090
|
-
for (let j = 0; j < numTabs; j++) {
|
|
16091
|
-
const tabStartDist = gapSize * (j + 1) + physicalTabLength * j;
|
|
16092
|
-
tabsOnSegment.push({
|
|
16093
|
-
start: tabStartDist,
|
|
16094
|
-
end: tabStartDist + physicalTabLength
|
|
16095
|
-
});
|
|
16096
|
-
}
|
|
16097
|
-
const extrusion = normalVec.multiply(tabWidth);
|
|
16098
|
-
for (let j = 0; j <= numTabs; j++) {
|
|
16099
|
-
const gapStartDist = j === 0 ? 0 : tabsOnSegment[j - 1].end;
|
|
16100
|
-
const gapEndDist = j === numTabs ? segmentLength : tabsOnSegment[j].start;
|
|
16101
|
-
const gapLength = gapEndDist - gapStartDist;
|
|
16102
|
-
if (gapLength < 1e-6) continue;
|
|
16103
|
-
if (isAxisAligned) {
|
|
16104
|
-
const width = isHorizontal ? gapLength : tabWidth;
|
|
16105
|
-
const height = isHorizontal ? tabWidth : gapLength;
|
|
16106
|
-
const gapCenterAlongSegment = Flatten.point(p1.x, p1.y).translate(
|
|
16107
|
-
segmentDirVec.multiply(gapStartDist + gapLength / 2)
|
|
16108
|
-
);
|
|
16109
|
-
const center = gapCenterAlongSegment.translate(extrusion.multiply(0.5));
|
|
16110
|
-
tabCutouts.push({
|
|
16111
|
-
type: "pcb_cutout",
|
|
16112
|
-
shape: "rect",
|
|
16113
|
-
center,
|
|
16114
|
-
width,
|
|
16115
|
-
height,
|
|
16116
|
-
corner_radius: Math.min(width, height) / 2
|
|
16117
|
-
});
|
|
16118
|
-
} else {
|
|
16119
|
-
const width = gapLength;
|
|
16120
|
-
const height = tabWidth;
|
|
16121
|
-
const gapCenterAlongSegment = Flatten.point(p1.x, p1.y).translate(
|
|
16122
|
-
segmentDirVec.multiply(gapStartDist + gapLength / 2)
|
|
16123
|
-
);
|
|
16124
|
-
const center = gapCenterAlongSegment.translate(extrusion.multiply(0.5));
|
|
16125
|
-
const rotationDeg = segmentDirVec.slope * 180 / Math.PI;
|
|
16126
|
-
tabCutouts.push({
|
|
16127
|
-
type: "pcb_cutout",
|
|
16128
|
-
shape: "rect",
|
|
16129
|
-
center,
|
|
16130
|
-
width,
|
|
16131
|
-
height,
|
|
16132
|
-
rotation: rotationDeg,
|
|
16133
|
-
corner_radius: Math.min(width, height) / 2
|
|
16134
|
-
});
|
|
16135
|
-
}
|
|
15876
|
+
const numBitesInGap = 2;
|
|
15877
|
+
const totalBitesLength = numBitesInGap * mouseBiteHoleDiameter + (numBitesInGap - 1) * mouseBiteHoleSpacing;
|
|
15878
|
+
let effectiveGapLength;
|
|
15879
|
+
if (mouseBites) {
|
|
15880
|
+
effectiveGapLength = totalBitesLength;
|
|
15881
|
+
} else {
|
|
15882
|
+
effectiveGapLength = gapLength;
|
|
16136
15883
|
}
|
|
15884
|
+
effectiveGapLength = Math.min(effectiveGapLength, segmentLength * 0.9);
|
|
15885
|
+
const gapStartDist = (segmentLength - effectiveGapLength) / 2;
|
|
15886
|
+
const gapEndDist = gapStartDist + effectiveGapLength;
|
|
16137
15887
|
if (mouseBites) {
|
|
16138
|
-
const
|
|
16139
|
-
|
|
16140
|
-
const
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
|
|
16145
|
-
|
|
16146
|
-
const biteDist = biteStartOffset + k * holeSpacing;
|
|
16147
|
-
const pos = Flatten.point(p1.x, p1.y).translate(
|
|
16148
|
-
segmentDirVec.multiply(biteDist)
|
|
16149
|
-
);
|
|
16150
|
-
mouseBiteHoles.push({
|
|
16151
|
-
x: pos.x,
|
|
16152
|
-
y: pos.y
|
|
16153
|
-
});
|
|
15888
|
+
const holeAndSpacing = mouseBiteHoleDiameter + mouseBiteHoleSpacing;
|
|
15889
|
+
if (effectiveGapLength >= totalBitesLength && holeAndSpacing > 0) {
|
|
15890
|
+
const firstBiteCenterOffsetInGap = (effectiveGapLength - totalBitesLength) / 2 + mouseBiteHoleDiameter / 2;
|
|
15891
|
+
const firstBiteDistFromP1 = gapStartDist + firstBiteCenterOffsetInGap;
|
|
15892
|
+
for (let k = 0; k < numBitesInGap; k++) {
|
|
15893
|
+
const biteDist = firstBiteDistFromP1 + k * holeAndSpacing;
|
|
15894
|
+
const pos = p1.translate(segmentDir.multiply(biteDist));
|
|
15895
|
+
mouseBiteHoles.push({ x: pos.x, y: pos.y });
|
|
16154
15896
|
}
|
|
16155
15897
|
}
|
|
16156
15898
|
}
|
|
15899
|
+
const p_prev_ = outline[(i - 1 + outline.length) % outline.length];
|
|
15900
|
+
const p_next_ = outline[(i + 2) % outline.length];
|
|
15901
|
+
let start_ext = 0;
|
|
15902
|
+
let end_ext = 0;
|
|
15903
|
+
if (p_prev_ && p_next_) {
|
|
15904
|
+
const vec_in_p1 = Flatten.vector(Flatten.point(p_prev_.x, p_prev_.y), p1);
|
|
15905
|
+
const p1_cross = vec_in_p1.cross(segmentVec);
|
|
15906
|
+
const is_p1_convex = is_ccw ? p1_cross > 1e-9 : p1_cross < -1e-9;
|
|
15907
|
+
const vec_out_p2 = Flatten.vector(p2, Flatten.point(p_next_.x, p_next_.y));
|
|
15908
|
+
const p2_cross = segmentVec.cross(vec_out_p2);
|
|
15909
|
+
const is_p2_convex = is_ccw ? p2_cross > 1e-9 : p2_cross < -1e-9;
|
|
15910
|
+
start_ext = is_p1_convex ? cutoutWidth : 0;
|
|
15911
|
+
end_ext = is_p2_convex ? cutoutWidth : 0;
|
|
15912
|
+
}
|
|
15913
|
+
const cutoutParts = [
|
|
15914
|
+
{ start: 0 - start_ext, end: gapStartDist },
|
|
15915
|
+
{ start: gapEndDist, end: segmentLength + end_ext }
|
|
15916
|
+
];
|
|
15917
|
+
const extrusion = normalVec.multiply(cutoutWidth);
|
|
15918
|
+
for (const part of cutoutParts) {
|
|
15919
|
+
const partLength = part.end - part.start;
|
|
15920
|
+
if (partLength < 1e-6) continue;
|
|
15921
|
+
const partCenterAlongSegment = p1.translate(
|
|
15922
|
+
segmentDir.multiply(part.start + partLength / 2)
|
|
15923
|
+
);
|
|
15924
|
+
const center = partCenterAlongSegment.translate(extrusion.multiply(0.5));
|
|
15925
|
+
const width = partLength;
|
|
15926
|
+
const height = cutoutWidth;
|
|
15927
|
+
const rotationDeg = segmentDir.slope * 180 / Math.PI;
|
|
15928
|
+
tabCutouts.push({
|
|
15929
|
+
type: "pcb_cutout",
|
|
15930
|
+
shape: "rect",
|
|
15931
|
+
center: { x: center.x, y: center.y },
|
|
15932
|
+
width,
|
|
15933
|
+
height,
|
|
15934
|
+
rotation: rotationDeg,
|
|
15935
|
+
corner_radius: cutoutWidth / 2
|
|
15936
|
+
});
|
|
15937
|
+
}
|
|
16157
15938
|
}
|
|
16158
15939
|
return { tabCutouts, mouseBiteHoles };
|
|
16159
15940
|
};
|
|
16160
15941
|
function generatePanelTabsAndMouseBites(boards, options) {
|
|
16161
15942
|
const finalTabCutouts = [];
|
|
16162
15943
|
const allMouseBites = [];
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
15944
|
+
const { tabWidth, tabLength, mouseBites: useMouseBites } = options;
|
|
15945
|
+
const processedBoards = boards.map((board) => {
|
|
15946
|
+
if ((!board.outline || board.outline.length === 0) && board.width && board.height) {
|
|
15947
|
+
const w2 = board.width / 2;
|
|
15948
|
+
const h2 = board.height / 2;
|
|
15949
|
+
return {
|
|
15950
|
+
...board,
|
|
15951
|
+
outline: [
|
|
15952
|
+
{ x: board.center.x - w2, y: board.center.y - h2 },
|
|
15953
|
+
{ x: board.center.x + w2, y: board.center.y - h2 },
|
|
15954
|
+
{ x: board.center.x + w2, y: board.center.y + h2 },
|
|
15955
|
+
{ x: board.center.x - w2, y: board.center.y + h2 }
|
|
15956
|
+
]
|
|
15957
|
+
};
|
|
15958
|
+
}
|
|
15959
|
+
return board;
|
|
15960
|
+
});
|
|
15961
|
+
for (const board of processedBoards) {
|
|
16166
15962
|
if (board.outline && board.outline.length > 0) {
|
|
16167
|
-
const mouseBiteDiameter2 =
|
|
15963
|
+
const mouseBiteDiameter2 = tabWidth * 0.45;
|
|
16168
15964
|
const mouseBiteSpacing = mouseBiteDiameter2 * 0.1;
|
|
16169
|
-
const generated =
|
|
16170
|
-
|
|
16171
|
-
|
|
16172
|
-
|
|
16173
|
-
|
|
16174
|
-
|
|
16175
|
-
|
|
16176
|
-
}
|
|
16177
|
-
);
|
|
15965
|
+
const generated = generateCutoutsAndMousebitesForOutline(board.outline, {
|
|
15966
|
+
gapLength: tabLength,
|
|
15967
|
+
cutoutWidth: tabWidth,
|
|
15968
|
+
mouseBites: useMouseBites,
|
|
15969
|
+
mouseBiteHoleDiameter: mouseBiteDiameter2,
|
|
15970
|
+
mouseBiteHoleSpacing: mouseBiteSpacing
|
|
15971
|
+
});
|
|
16178
15972
|
finalTabCutouts.push(...generated.tabCutouts);
|
|
16179
15973
|
allMouseBites.push(...generated.mouseBiteHoles);
|
|
16180
|
-
} else {
|
|
16181
|
-
for (const edge of ["top", "bottom", "left", "right"]) {
|
|
16182
|
-
const edgeTabs = generateTabsForEdge({
|
|
16183
|
-
board,
|
|
16184
|
-
edge,
|
|
16185
|
-
otherBoards,
|
|
16186
|
-
options
|
|
16187
|
-
});
|
|
16188
|
-
for (const tab of edgeTabs) {
|
|
16189
|
-
const tabWidthDimension = Math.min(tab.width, tab.height);
|
|
16190
|
-
finalTabCutouts.push({
|
|
16191
|
-
type: "pcb_cutout",
|
|
16192
|
-
shape: "rect",
|
|
16193
|
-
center: tab.center,
|
|
16194
|
-
width: tab.width,
|
|
16195
|
-
height: tab.height,
|
|
16196
|
-
corner_radius: tabWidthDimension / 2
|
|
16197
|
-
});
|
|
16198
|
-
}
|
|
16199
|
-
if (options.mouseBites) {
|
|
16200
|
-
const edgeMouseBites = generateMouseBitesForEdge({
|
|
16201
|
-
board,
|
|
16202
|
-
edge,
|
|
16203
|
-
edgeTabs,
|
|
16204
|
-
allBoards: otherBoards,
|
|
16205
|
-
options
|
|
16206
|
-
});
|
|
16207
|
-
allMouseBites.push(...edgeMouseBites);
|
|
16208
|
-
}
|
|
16209
|
-
}
|
|
16210
15974
|
}
|
|
16211
15975
|
}
|
|
16212
15976
|
const tabCutouts = finalTabCutouts.map((tab, index) => ({
|
|
16213
15977
|
...tab,
|
|
16214
15978
|
pcb_cutout_id: `panel_tab_${index}`
|
|
16215
15979
|
}));
|
|
16216
|
-
const mouseBiteDiameter =
|
|
15980
|
+
const mouseBiteDiameter = tabWidth * 0.45;
|
|
16217
15981
|
const mouseBiteHoles = allMouseBites.map((bite, index) => ({
|
|
16218
15982
|
type: "pcb_hole",
|
|
16219
15983
|
pcb_hole_id: `panel_mouse_bite_${index}`,
|
|
@@ -16561,10 +16325,10 @@ var Jumper = class extends NormalComponent3 {
|
|
|
16561
16325
|
};
|
|
16562
16326
|
for (const trace of traces) {
|
|
16563
16327
|
if (!trace.route) continue;
|
|
16564
|
-
for (const
|
|
16565
|
-
if (
|
|
16566
|
-
|
|
16567
|
-
|
|
16328
|
+
for (const segment2 of trace.route) {
|
|
16329
|
+
if (segment2.route_type !== "wire") continue;
|
|
16330
|
+
segment2.start_pcb_port_id = updatePortId(segment2.start_pcb_port_id);
|
|
16331
|
+
segment2.end_pcb_port_id = updatePortId(segment2.end_pcb_port_id);
|
|
16568
16332
|
}
|
|
16569
16333
|
}
|
|
16570
16334
|
}
|
|
@@ -16751,10 +16515,10 @@ var SolderJumper = class extends NormalComponent3 {
|
|
|
16751
16515
|
};
|
|
16752
16516
|
for (const trace of traces) {
|
|
16753
16517
|
if (!trace.route) continue;
|
|
16754
|
-
for (const
|
|
16755
|
-
if (
|
|
16756
|
-
|
|
16757
|
-
|
|
16518
|
+
for (const segment2 of trace.route) {
|
|
16519
|
+
if (segment2.route_type !== "wire") continue;
|
|
16520
|
+
segment2.start_pcb_port_id = updatePortId(segment2.start_pcb_port_id);
|
|
16521
|
+
segment2.end_pcb_port_id = updatePortId(segment2.end_pcb_port_id);
|
|
16758
16522
|
}
|
|
16759
16523
|
}
|
|
16760
16524
|
}
|
|
@@ -19417,7 +19181,7 @@ import { identity as identity5 } from "transformation-matrix";
|
|
|
19417
19181
|
var package_default = {
|
|
19418
19182
|
name: "@tscircuit/core",
|
|
19419
19183
|
type: "module",
|
|
19420
|
-
version: "0.0.
|
|
19184
|
+
version: "0.0.907",
|
|
19421
19185
|
types: "dist/index.d.ts",
|
|
19422
19186
|
main: "dist/index.js",
|
|
19423
19187
|
module: "dist/index.js",
|
|
@@ -19480,7 +19244,7 @@ var package_default = {
|
|
|
19480
19244
|
"circuit-json-to-connectivity-map": "^0.0.22",
|
|
19481
19245
|
"circuit-json-to-gltf": "^0.0.31",
|
|
19482
19246
|
"circuit-json-to-simple-3d": "^0.0.9",
|
|
19483
|
-
"circuit-json-to-spice": "^0.0.
|
|
19247
|
+
"circuit-json-to-spice": "^0.0.30",
|
|
19484
19248
|
"circuit-to-svg": "^0.0.284",
|
|
19485
19249
|
concurrently: "^9.1.2",
|
|
19486
19250
|
"connectivity-map": "^1.0.0",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.908",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"circuit-json-to-connectivity-map": "^0.0.22",
|
|
65
65
|
"circuit-json-to-gltf": "^0.0.31",
|
|
66
66
|
"circuit-json-to-simple-3d": "^0.0.9",
|
|
67
|
-
"circuit-json-to-spice": "^0.0.
|
|
67
|
+
"circuit-json-to-spice": "^0.0.30",
|
|
68
68
|
"circuit-to-svg": "^0.0.284",
|
|
69
69
|
"concurrently": "^9.1.2",
|
|
70
70
|
"connectivity-map": "^1.0.0",
|