circuit-to-svg 0.0.196 → 0.0.198
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 +35 -5
- package/dist/index.js +1156 -145
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1743,7 +1743,7 @@ function getSoftwareUsedString(circuitJson) {
|
|
|
1743
1743
|
var package_default = {
|
|
1744
1744
|
name: "circuit-to-svg",
|
|
1745
1745
|
type: "module",
|
|
1746
|
-
version: "0.0.
|
|
1746
|
+
version: "0.0.197",
|
|
1747
1747
|
description: "Convert Circuit JSON to SVG",
|
|
1748
1748
|
main: "dist/index.js",
|
|
1749
1749
|
files: [
|
|
@@ -1767,7 +1767,7 @@ var package_default = {
|
|
|
1767
1767
|
"bun-match-svg": "^0.0.12",
|
|
1768
1768
|
esbuild: "^0.20.2",
|
|
1769
1769
|
"performance-now": "^2.1.0",
|
|
1770
|
-
"circuit-json": "^0.0.
|
|
1770
|
+
"circuit-json": "^0.0.261",
|
|
1771
1771
|
react: "19.1.0",
|
|
1772
1772
|
"react-cosmos": "7.0.0",
|
|
1773
1773
|
"react-cosmos-plugin-vite": "7.0.0",
|
|
@@ -1783,6 +1783,7 @@ var package_default = {
|
|
|
1783
1783
|
dependencies: {
|
|
1784
1784
|
"@types/node": "^22.5.5",
|
|
1785
1785
|
"bun-types": "^1.1.40",
|
|
1786
|
+
"calculate-elbow": "0.0.12",
|
|
1786
1787
|
svgson: "^5.3.1",
|
|
1787
1788
|
"transformation-matrix": "^2.16.1"
|
|
1788
1789
|
}
|
|
@@ -3070,6 +3071,1012 @@ function createSvgObjectFromAssemblyBoundary(transform, minX, minY, maxX, maxY)
|
|
|
3070
3071
|
};
|
|
3071
3072
|
}
|
|
3072
3073
|
|
|
3074
|
+
// lib/pinout/convert-circuit-json-to-pinout-svg.ts
|
|
3075
|
+
import { stringify as stringify3 } from "svgson";
|
|
3076
|
+
import { su as su6 } from "@tscircuit/circuit-json-util";
|
|
3077
|
+
import {
|
|
3078
|
+
applyToPoint as applyToPoint34,
|
|
3079
|
+
compose as compose7,
|
|
3080
|
+
scale as scale4,
|
|
3081
|
+
translate as translate7
|
|
3082
|
+
} from "transformation-matrix";
|
|
3083
|
+
|
|
3084
|
+
// lib/pinout/svg-object-fns/create-svg-objects-from-pinout-board.ts
|
|
3085
|
+
import { applyToPoint as applyToPoint28 } from "transformation-matrix";
|
|
3086
|
+
import { su as su4 } from "@tscircuit/circuit-json-util";
|
|
3087
|
+
var BOARD_FILL_COLOR = "rgb(26, 115, 143)";
|
|
3088
|
+
var BOARD_STROKE_COLOR = "rgba(0,0,0,0.9)";
|
|
3089
|
+
function createSvgObjectsFromPinoutBoard(pcbBoard, ctx) {
|
|
3090
|
+
const { transform, soup } = ctx;
|
|
3091
|
+
const { width, height, center, outline } = pcbBoard;
|
|
3092
|
+
let path;
|
|
3093
|
+
if (outline && Array.isArray(outline) && outline.length >= 3) {
|
|
3094
|
+
path = outline.map((point, index) => {
|
|
3095
|
+
const [x, y] = applyToPoint28(transform, [point.x, point.y]);
|
|
3096
|
+
return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
|
|
3097
|
+
}).join(" ");
|
|
3098
|
+
} else {
|
|
3099
|
+
const halfWidth = width / 2;
|
|
3100
|
+
const halfHeight = height / 2;
|
|
3101
|
+
const topLeft = applyToPoint28(transform, [
|
|
3102
|
+
center.x - halfWidth,
|
|
3103
|
+
center.y - halfHeight
|
|
3104
|
+
]);
|
|
3105
|
+
const topRight = applyToPoint28(transform, [
|
|
3106
|
+
center.x + halfWidth,
|
|
3107
|
+
center.y - halfHeight
|
|
3108
|
+
]);
|
|
3109
|
+
const bottomRight = applyToPoint28(transform, [
|
|
3110
|
+
center.x + halfWidth,
|
|
3111
|
+
center.y + halfHeight
|
|
3112
|
+
]);
|
|
3113
|
+
const bottomLeft = applyToPoint28(transform, [
|
|
3114
|
+
center.x - halfWidth,
|
|
3115
|
+
center.y + halfHeight
|
|
3116
|
+
]);
|
|
3117
|
+
path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]}`;
|
|
3118
|
+
}
|
|
3119
|
+
path += " Z";
|
|
3120
|
+
const cutlery = su4(soup).pcb_cutout.list();
|
|
3121
|
+
for (const cutout of cutlery) {
|
|
3122
|
+
if (cutout.shape === "rect") {
|
|
3123
|
+
const { x, y, width: width2, height: height2 } = cutout.center ? (() => {
|
|
3124
|
+
const { x: x2, y: y2 } = cutout.center;
|
|
3125
|
+
const { width: width3, height: height3 } = cutout;
|
|
3126
|
+
return { x: x2, y: y2, width: width3, height: height3 };
|
|
3127
|
+
})() : { x: 0, y: 0, width: 0, height: 0 };
|
|
3128
|
+
const halfWidth = width2 / 2;
|
|
3129
|
+
const halfHeight = height2 / 2;
|
|
3130
|
+
const [tl, tr, br, bl] = [
|
|
3131
|
+
applyToPoint28(transform, [x - halfWidth, y - halfHeight]),
|
|
3132
|
+
applyToPoint28(transform, [x + halfWidth, y - halfHeight]),
|
|
3133
|
+
applyToPoint28(transform, [x + halfWidth, y + halfHeight]),
|
|
3134
|
+
applyToPoint28(transform, [x - halfWidth, y + halfHeight])
|
|
3135
|
+
];
|
|
3136
|
+
path += ` M ${tl[0]} ${tl[1]} L ${tr[0]} ${tr[1]} L ${br[0]} ${br[1]} L ${bl[0]} ${bl[1]} Z`;
|
|
3137
|
+
} else if (cutout.shape === "circle") {
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
return [
|
|
3141
|
+
{
|
|
3142
|
+
name: "path",
|
|
3143
|
+
type: "element",
|
|
3144
|
+
value: "",
|
|
3145
|
+
children: [],
|
|
3146
|
+
attributes: {
|
|
3147
|
+
class: "pinout-board",
|
|
3148
|
+
d: path,
|
|
3149
|
+
fill: BOARD_FILL_COLOR,
|
|
3150
|
+
stroke: BOARD_STROKE_COLOR,
|
|
3151
|
+
"fill-rule": "evenodd",
|
|
3152
|
+
"stroke-opacity": "0.8",
|
|
3153
|
+
"stroke-width": (0.2 * Math.abs(transform.a)).toString()
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
];
|
|
3157
|
+
}
|
|
3158
|
+
|
|
3159
|
+
// lib/pinout/svg-object-fns/create-svg-objects-from-pinout-component.ts
|
|
3160
|
+
import { su as su5 } from "@tscircuit/circuit-json-util";
|
|
3161
|
+
import { applyToPoint as applyToPoint29 } from "transformation-matrix";
|
|
3162
|
+
var COMPONENT_FILL_COLOR = "rgba(120, 120, 120, 0.6)";
|
|
3163
|
+
var COMPONENT_LABEL_COLOR = "rgba(255, 255, 255, 0.9)";
|
|
3164
|
+
function createSvgObjectsFromPinoutComponent(elm, ctx) {
|
|
3165
|
+
const { transform, soup } = ctx;
|
|
3166
|
+
const { center, width, height, rotation = 0, source_component_id } = elm;
|
|
3167
|
+
const sourceComponent = su5(soup).source_component.get(source_component_id);
|
|
3168
|
+
if (!center || typeof width !== "number" || typeof height !== "number" || width === 0 || height === 0) {
|
|
3169
|
+
return [];
|
|
3170
|
+
}
|
|
3171
|
+
const [x, y] = applyToPoint29(transform, [center.x, center.y]);
|
|
3172
|
+
const scaledWidth = width * Math.abs(transform.a);
|
|
3173
|
+
const scaledHeight = height * Math.abs(transform.d);
|
|
3174
|
+
const transformStr = `translate(${x}, ${y}) rotate(${-rotation})`;
|
|
3175
|
+
const children = [
|
|
3176
|
+
{
|
|
3177
|
+
name: "rect",
|
|
3178
|
+
type: "element",
|
|
3179
|
+
attributes: {
|
|
3180
|
+
class: "pinout-component-box",
|
|
3181
|
+
x: (-scaledWidth / 2).toString(),
|
|
3182
|
+
y: (-scaledHeight / 2).toString(),
|
|
3183
|
+
width: scaledWidth.toString(),
|
|
3184
|
+
height: scaledHeight.toString(),
|
|
3185
|
+
fill: COMPONENT_FILL_COLOR
|
|
3186
|
+
},
|
|
3187
|
+
value: "",
|
|
3188
|
+
children: []
|
|
3189
|
+
}
|
|
3190
|
+
];
|
|
3191
|
+
if (sourceComponent?.name) {
|
|
3192
|
+
const isTall = scaledHeight > scaledWidth * 1.5;
|
|
3193
|
+
const labelFontSize = Math.min(scaledWidth, scaledHeight) * 0.4;
|
|
3194
|
+
children.push({
|
|
3195
|
+
name: "text",
|
|
3196
|
+
type: "element",
|
|
3197
|
+
attributes: {
|
|
3198
|
+
x: "0",
|
|
3199
|
+
y: "0",
|
|
3200
|
+
fill: COMPONENT_LABEL_COLOR,
|
|
3201
|
+
"font-size": `${labelFontSize}px`,
|
|
3202
|
+
"font-family": "sans-serif",
|
|
3203
|
+
"text-anchor": "middle",
|
|
3204
|
+
"dominant-baseline": "middle",
|
|
3205
|
+
transform: isTall ? "rotate(90)" : ""
|
|
3206
|
+
},
|
|
3207
|
+
children: [
|
|
3208
|
+
{
|
|
3209
|
+
type: "text",
|
|
3210
|
+
value: sourceComponent.name,
|
|
3211
|
+
name: "",
|
|
3212
|
+
attributes: {},
|
|
3213
|
+
children: []
|
|
3214
|
+
}
|
|
3215
|
+
],
|
|
3216
|
+
value: ""
|
|
3217
|
+
});
|
|
3218
|
+
}
|
|
3219
|
+
return [
|
|
3220
|
+
{
|
|
3221
|
+
name: "g",
|
|
3222
|
+
type: "element",
|
|
3223
|
+
attributes: {
|
|
3224
|
+
transform: transformStr
|
|
3225
|
+
},
|
|
3226
|
+
children,
|
|
3227
|
+
value: ""
|
|
3228
|
+
}
|
|
3229
|
+
];
|
|
3230
|
+
}
|
|
3231
|
+
|
|
3232
|
+
// lib/pinout/svg-object-fns/create-svg-objects-from-pinout-hole.ts
|
|
3233
|
+
import { applyToPoint as applyToPoint30 } from "transformation-matrix";
|
|
3234
|
+
var HOLE_COLOR4 = "rgb(50, 50, 50)";
|
|
3235
|
+
function createSvgObjectsFromPinoutHole(hole, ctx) {
|
|
3236
|
+
const { transform } = ctx;
|
|
3237
|
+
const [x, y] = applyToPoint30(transform, [hole.x, hole.y]);
|
|
3238
|
+
if (hole.hole_shape === "circle" || hole.hole_shape === "square") {
|
|
3239
|
+
const scaledDiameter = hole.hole_diameter * Math.abs(transform.a);
|
|
3240
|
+
const radius = scaledDiameter / 2;
|
|
3241
|
+
if (hole.hole_shape === "circle") {
|
|
3242
|
+
return [
|
|
3243
|
+
{
|
|
3244
|
+
name: "circle",
|
|
3245
|
+
type: "element",
|
|
3246
|
+
attributes: {
|
|
3247
|
+
class: "pinout-hole",
|
|
3248
|
+
cx: x.toString(),
|
|
3249
|
+
cy: y.toString(),
|
|
3250
|
+
r: radius.toString(),
|
|
3251
|
+
fill: HOLE_COLOR4
|
|
3252
|
+
},
|
|
3253
|
+
children: [],
|
|
3254
|
+
value: ""
|
|
3255
|
+
}
|
|
3256
|
+
];
|
|
3257
|
+
}
|
|
3258
|
+
return [
|
|
3259
|
+
{
|
|
3260
|
+
name: "rect",
|
|
3261
|
+
type: "element",
|
|
3262
|
+
attributes: {
|
|
3263
|
+
class: "pinout-hole",
|
|
3264
|
+
x: (x - radius).toString(),
|
|
3265
|
+
y: (y - radius).toString(),
|
|
3266
|
+
width: scaledDiameter.toString(),
|
|
3267
|
+
height: scaledDiameter.toString(),
|
|
3268
|
+
fill: HOLE_COLOR4
|
|
3269
|
+
},
|
|
3270
|
+
children: [],
|
|
3271
|
+
value: ""
|
|
3272
|
+
}
|
|
3273
|
+
];
|
|
3274
|
+
}
|
|
3275
|
+
if (hole.hole_shape === "oval") {
|
|
3276
|
+
const scaledWidth = hole.hole_width * Math.abs(transform.a);
|
|
3277
|
+
const scaledHeight = hole.hole_height * Math.abs(transform.a);
|
|
3278
|
+
const rx = scaledWidth / 2;
|
|
3279
|
+
const ry = scaledHeight / 2;
|
|
3280
|
+
return [
|
|
3281
|
+
{
|
|
3282
|
+
name: "ellipse",
|
|
3283
|
+
type: "element",
|
|
3284
|
+
attributes: {
|
|
3285
|
+
class: "pinout-hole",
|
|
3286
|
+
cx: x.toString(),
|
|
3287
|
+
cy: y.toString(),
|
|
3288
|
+
rx: rx.toString(),
|
|
3289
|
+
ry: ry.toString(),
|
|
3290
|
+
fill: HOLE_COLOR4
|
|
3291
|
+
},
|
|
3292
|
+
children: [],
|
|
3293
|
+
value: ""
|
|
3294
|
+
}
|
|
3295
|
+
];
|
|
3296
|
+
}
|
|
3297
|
+
return [];
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
// lib/pinout/svg-object-fns/create-svg-objects-from-pinout-plated-hole.ts
|
|
3301
|
+
import { applyToPoint as applyToPoint31 } from "transformation-matrix";
|
|
3302
|
+
var PAD_COLOR3 = "rgb(218, 165, 32)";
|
|
3303
|
+
var HOLE_COLOR5 = "rgb(40, 40, 40)";
|
|
3304
|
+
function createSvgObjectsFromPinoutPlatedHole(hole, ctx) {
|
|
3305
|
+
const { transform } = ctx;
|
|
3306
|
+
const [x, y] = applyToPoint31(transform, [hole.x, hole.y]);
|
|
3307
|
+
if (hole.shape === "pill") {
|
|
3308
|
+
const scaledOuterWidth = hole.outer_width * Math.abs(transform.a);
|
|
3309
|
+
const scaledOuterHeight = hole.outer_height * Math.abs(transform.a);
|
|
3310
|
+
const scaledHoleWidth = hole.hole_width * Math.abs(transform.a);
|
|
3311
|
+
const scaledHoleHeight = hole.hole_height * Math.abs(transform.a);
|
|
3312
|
+
const outerRadiusX = scaledOuterWidth / 2;
|
|
3313
|
+
const straightLength = scaledOuterHeight - scaledOuterWidth;
|
|
3314
|
+
const innerRadiusX = scaledHoleWidth / 2;
|
|
3315
|
+
return [
|
|
3316
|
+
{
|
|
3317
|
+
name: "g",
|
|
3318
|
+
type: "element",
|
|
3319
|
+
children: [
|
|
3320
|
+
// Outer pill shape
|
|
3321
|
+
{
|
|
3322
|
+
name: "path",
|
|
3323
|
+
type: "element",
|
|
3324
|
+
attributes: {
|
|
3325
|
+
class: "pinout-hole-outer",
|
|
3326
|
+
fill: PAD_COLOR3,
|
|
3327
|
+
d: `M${x - outerRadiusX},${y - straightLength / 2} v${straightLength} a${outerRadiusX},${outerRadiusX} 0 0 0 ${scaledOuterWidth},0 v-${straightLength} a${outerRadiusX},${outerRadiusX} 0 0 0 -${scaledOuterWidth},0 z`
|
|
3328
|
+
},
|
|
3329
|
+
value: "",
|
|
3330
|
+
children: []
|
|
3331
|
+
},
|
|
3332
|
+
// Inner pill shape
|
|
3333
|
+
{
|
|
3334
|
+
name: "path",
|
|
3335
|
+
type: "element",
|
|
3336
|
+
attributes: {
|
|
3337
|
+
class: "pinout-hole-inner",
|
|
3338
|
+
fill: HOLE_COLOR5,
|
|
3339
|
+
d: `M${x - innerRadiusX},${y - (scaledHoleHeight - scaledHoleWidth) / 2} v${scaledHoleHeight - scaledHoleWidth} a${innerRadiusX},${innerRadiusX} 0 0 0 ${scaledHoleWidth},0 v-${scaledHoleHeight - scaledHoleWidth} a${innerRadiusX},${innerRadiusX} 0 0 0 -${scaledHoleWidth},0 z`
|
|
3340
|
+
},
|
|
3341
|
+
value: "",
|
|
3342
|
+
children: []
|
|
3343
|
+
}
|
|
3344
|
+
],
|
|
3345
|
+
value: "",
|
|
3346
|
+
attributes: {}
|
|
3347
|
+
}
|
|
3348
|
+
];
|
|
3349
|
+
}
|
|
3350
|
+
if (hole.shape === "circle") {
|
|
3351
|
+
const scaledOuterWidth = hole.outer_diameter * Math.abs(transform.a);
|
|
3352
|
+
const scaledOuterHeight = hole.outer_diameter * Math.abs(transform.a);
|
|
3353
|
+
const scaledHoleWidth = hole.hole_diameter * Math.abs(transform.a);
|
|
3354
|
+
const scaledHoleHeight = hole.hole_diameter * Math.abs(transform.a);
|
|
3355
|
+
const outerRadius = Math.min(scaledOuterWidth, scaledOuterHeight) / 2;
|
|
3356
|
+
const innerRadius = Math.min(scaledHoleWidth, scaledHoleHeight) / 2;
|
|
3357
|
+
return [
|
|
3358
|
+
{
|
|
3359
|
+
name: "g",
|
|
3360
|
+
type: "element",
|
|
3361
|
+
children: [
|
|
3362
|
+
{
|
|
3363
|
+
name: "circle",
|
|
3364
|
+
type: "element",
|
|
3365
|
+
attributes: {
|
|
3366
|
+
class: "pinout-hole-outer",
|
|
3367
|
+
fill: PAD_COLOR3,
|
|
3368
|
+
cx: x.toString(),
|
|
3369
|
+
cy: y.toString(),
|
|
3370
|
+
r: outerRadius.toString()
|
|
3371
|
+
},
|
|
3372
|
+
value: "",
|
|
3373
|
+
children: []
|
|
3374
|
+
},
|
|
3375
|
+
{
|
|
3376
|
+
name: "circle",
|
|
3377
|
+
type: "element",
|
|
3378
|
+
attributes: {
|
|
3379
|
+
class: "pinout-hole-inner",
|
|
3380
|
+
fill: HOLE_COLOR5,
|
|
3381
|
+
cx: x.toString(),
|
|
3382
|
+
cy: y.toString(),
|
|
3383
|
+
r: innerRadius.toString()
|
|
3384
|
+
},
|
|
3385
|
+
value: "",
|
|
3386
|
+
children: []
|
|
3387
|
+
}
|
|
3388
|
+
],
|
|
3389
|
+
value: "",
|
|
3390
|
+
attributes: {}
|
|
3391
|
+
}
|
|
3392
|
+
];
|
|
3393
|
+
}
|
|
3394
|
+
if (hole.shape === "circular_hole_with_rect_pad") {
|
|
3395
|
+
const scaledHoleDiameter = hole.hole_diameter * Math.abs(transform.a);
|
|
3396
|
+
const scaledRectPadWidth = hole.rect_pad_width * Math.abs(transform.a);
|
|
3397
|
+
const scaledRectPadHeight = hole.rect_pad_height * Math.abs(transform.a);
|
|
3398
|
+
const holeRadius = scaledHoleDiameter / 2;
|
|
3399
|
+
return [
|
|
3400
|
+
{
|
|
3401
|
+
name: "g",
|
|
3402
|
+
type: "element",
|
|
3403
|
+
children: [
|
|
3404
|
+
// Rectangular pad (outer shape)
|
|
3405
|
+
{
|
|
3406
|
+
name: "rect",
|
|
3407
|
+
type: "element",
|
|
3408
|
+
attributes: {
|
|
3409
|
+
class: "pinout-hole-outer-pad",
|
|
3410
|
+
fill: PAD_COLOR3,
|
|
3411
|
+
x: (x - scaledRectPadWidth / 2).toString(),
|
|
3412
|
+
y: (y - scaledRectPadHeight / 2).toString(),
|
|
3413
|
+
width: scaledRectPadWidth.toString(),
|
|
3414
|
+
height: scaledRectPadHeight.toString()
|
|
3415
|
+
},
|
|
3416
|
+
value: "",
|
|
3417
|
+
children: []
|
|
3418
|
+
},
|
|
3419
|
+
// Circular hole inside the rectangle
|
|
3420
|
+
{
|
|
3421
|
+
name: "circle",
|
|
3422
|
+
type: "element",
|
|
3423
|
+
attributes: {
|
|
3424
|
+
class: "pinout-hole-inner",
|
|
3425
|
+
fill: HOLE_COLOR5,
|
|
3426
|
+
cx: x.toString(),
|
|
3427
|
+
cy: y.toString(),
|
|
3428
|
+
r: holeRadius.toString()
|
|
3429
|
+
},
|
|
3430
|
+
value: "",
|
|
3431
|
+
children: []
|
|
3432
|
+
}
|
|
3433
|
+
],
|
|
3434
|
+
value: "",
|
|
3435
|
+
attributes: {}
|
|
3436
|
+
}
|
|
3437
|
+
];
|
|
3438
|
+
}
|
|
3439
|
+
if (hole.shape === "pill_hole_with_rect_pad") {
|
|
3440
|
+
const scaledRectPadWidth = hole.rect_pad_width * Math.abs(transform.a);
|
|
3441
|
+
const scaledRectPadHeight = hole.rect_pad_height * Math.abs(transform.a);
|
|
3442
|
+
const scaledHoleHeight = hole.hole_height * Math.abs(transform.a);
|
|
3443
|
+
const scaledHoleWidth = hole.hole_width * Math.abs(transform.a);
|
|
3444
|
+
const holeRadius = Math.min(scaledHoleHeight, scaledHoleWidth) / 2;
|
|
3445
|
+
return [
|
|
3446
|
+
{
|
|
3447
|
+
name: "g",
|
|
3448
|
+
type: "element",
|
|
3449
|
+
children: [
|
|
3450
|
+
// Rectangular pad (outer shape)
|
|
3451
|
+
{
|
|
3452
|
+
name: "rect",
|
|
3453
|
+
type: "element",
|
|
3454
|
+
attributes: {
|
|
3455
|
+
class: "pinout-hole-outer-pad",
|
|
3456
|
+
fill: PAD_COLOR3,
|
|
3457
|
+
x: (x - scaledRectPadWidth / 2).toString(),
|
|
3458
|
+
y: (y - scaledRectPadHeight / 2).toString(),
|
|
3459
|
+
width: scaledRectPadWidth.toString(),
|
|
3460
|
+
height: scaledRectPadHeight.toString()
|
|
3461
|
+
},
|
|
3462
|
+
value: "",
|
|
3463
|
+
children: []
|
|
3464
|
+
},
|
|
3465
|
+
// pill hole inside the rectangle
|
|
3466
|
+
{
|
|
3467
|
+
name: "rect",
|
|
3468
|
+
type: "element",
|
|
3469
|
+
attributes: {
|
|
3470
|
+
class: "pinout-hole-inner",
|
|
3471
|
+
fill: HOLE_COLOR5,
|
|
3472
|
+
x: (x - scaledHoleWidth / 2).toString(),
|
|
3473
|
+
y: (y - scaledHoleHeight / 2).toString(),
|
|
3474
|
+
width: scaledHoleWidth.toString(),
|
|
3475
|
+
height: scaledHoleHeight.toString(),
|
|
3476
|
+
rx: holeRadius.toString(),
|
|
3477
|
+
ry: holeRadius.toString()
|
|
3478
|
+
},
|
|
3479
|
+
value: "",
|
|
3480
|
+
children: []
|
|
3481
|
+
}
|
|
3482
|
+
],
|
|
3483
|
+
value: "",
|
|
3484
|
+
attributes: {}
|
|
3485
|
+
}
|
|
3486
|
+
];
|
|
3487
|
+
}
|
|
3488
|
+
if (hole.shape === "rotated_pill_hole_with_rect_pad") {
|
|
3489
|
+
const scaledRectPadWidth = hole.rect_pad_width * Math.abs(transform.a);
|
|
3490
|
+
const scaledRectPadHeight = hole.rect_pad_height * Math.abs(transform.a);
|
|
3491
|
+
const scaledHoleHeight = hole.hole_height * Math.abs(transform.a);
|
|
3492
|
+
const scaledHoleWidth = hole.hole_width * Math.abs(transform.a);
|
|
3493
|
+
const holeRadius = Math.min(scaledHoleHeight, scaledHoleWidth) / 2;
|
|
3494
|
+
return [
|
|
3495
|
+
{
|
|
3496
|
+
name: "g",
|
|
3497
|
+
type: "element",
|
|
3498
|
+
children: [
|
|
3499
|
+
{
|
|
3500
|
+
name: "rect",
|
|
3501
|
+
type: "element",
|
|
3502
|
+
attributes: {
|
|
3503
|
+
class: "pinout-hole-outer-pad",
|
|
3504
|
+
fill: PAD_COLOR3,
|
|
3505
|
+
x: (-scaledRectPadWidth / 2).toString(),
|
|
3506
|
+
y: (-scaledRectPadHeight / 2).toString(),
|
|
3507
|
+
width: scaledRectPadWidth.toString(),
|
|
3508
|
+
height: scaledRectPadHeight.toString(),
|
|
3509
|
+
transform: `translate(${x} ${y}) rotate(${-hole.rect_ccw_rotation})`
|
|
3510
|
+
},
|
|
3511
|
+
value: "",
|
|
3512
|
+
children: []
|
|
3513
|
+
},
|
|
3514
|
+
{
|
|
3515
|
+
name: "rect",
|
|
3516
|
+
type: "element",
|
|
3517
|
+
attributes: {
|
|
3518
|
+
class: "pinout-hole-inner",
|
|
3519
|
+
fill: HOLE_COLOR5,
|
|
3520
|
+
x: (-scaledHoleWidth / 2).toString(),
|
|
3521
|
+
y: (-scaledHoleHeight / 2).toString(),
|
|
3522
|
+
width: scaledHoleWidth.toString(),
|
|
3523
|
+
height: scaledHoleHeight.toString(),
|
|
3524
|
+
rx: holeRadius.toString(),
|
|
3525
|
+
ry: holeRadius.toString(),
|
|
3526
|
+
transform: `translate(${x} ${y}) rotate(${-hole.hole_ccw_rotation})`
|
|
3527
|
+
},
|
|
3528
|
+
value: "",
|
|
3529
|
+
children: []
|
|
3530
|
+
}
|
|
3531
|
+
],
|
|
3532
|
+
value: "",
|
|
3533
|
+
attributes: {}
|
|
3534
|
+
}
|
|
3535
|
+
];
|
|
3536
|
+
}
|
|
3537
|
+
return [];
|
|
3538
|
+
}
|
|
3539
|
+
|
|
3540
|
+
// lib/pinout/svg-object-fns/create-svg-objects-from-pinout-smt-pad.ts
|
|
3541
|
+
import { applyToPoint as applyToPoint32 } from "transformation-matrix";
|
|
3542
|
+
var PAD_COLOR4 = "rgb(218, 165, 32)";
|
|
3543
|
+
function createSvgObjectsFromPinoutSmtPad(pad, ctx) {
|
|
3544
|
+
const { transform } = ctx;
|
|
3545
|
+
if (pad.shape === "rect" || pad.shape === "rotated_rect") {
|
|
3546
|
+
const width = pad.width * Math.abs(transform.a);
|
|
3547
|
+
const height = pad.height * Math.abs(transform.d);
|
|
3548
|
+
const [x, y] = applyToPoint32(transform, [pad.x, pad.y]);
|
|
3549
|
+
if (pad.shape === "rotated_rect" && pad.ccw_rotation) {
|
|
3550
|
+
return [
|
|
3551
|
+
{
|
|
3552
|
+
name: "rect",
|
|
3553
|
+
type: "element",
|
|
3554
|
+
attributes: {
|
|
3555
|
+
class: "pinout-pad",
|
|
3556
|
+
fill: PAD_COLOR4,
|
|
3557
|
+
x: (-width / 2).toString(),
|
|
3558
|
+
y: (-height / 2).toString(),
|
|
3559
|
+
width: width.toString(),
|
|
3560
|
+
height: height.toString(),
|
|
3561
|
+
transform: `translate(${x} ${y}) rotate(${-pad.ccw_rotation})`,
|
|
3562
|
+
"data-layer": pad.layer
|
|
3563
|
+
},
|
|
3564
|
+
value: "",
|
|
3565
|
+
children: []
|
|
3566
|
+
}
|
|
3567
|
+
];
|
|
3568
|
+
}
|
|
3569
|
+
return [
|
|
3570
|
+
{
|
|
3571
|
+
name: "rect",
|
|
3572
|
+
type: "element",
|
|
3573
|
+
attributes: {
|
|
3574
|
+
class: "pinout-pad",
|
|
3575
|
+
fill: PAD_COLOR4,
|
|
3576
|
+
x: (x - width / 2).toString(),
|
|
3577
|
+
y: (y - height / 2).toString(),
|
|
3578
|
+
width: width.toString(),
|
|
3579
|
+
height: height.toString(),
|
|
3580
|
+
"data-layer": pad.layer
|
|
3581
|
+
},
|
|
3582
|
+
value: "",
|
|
3583
|
+
children: []
|
|
3584
|
+
}
|
|
3585
|
+
];
|
|
3586
|
+
}
|
|
3587
|
+
if (pad.shape === "pill") {
|
|
3588
|
+
const width = pad.width * Math.abs(transform.a);
|
|
3589
|
+
const height = pad.height * Math.abs(transform.d);
|
|
3590
|
+
const radius = pad.radius * Math.abs(transform.a);
|
|
3591
|
+
const [x, y] = applyToPoint32(transform, [pad.x, pad.y]);
|
|
3592
|
+
return [
|
|
3593
|
+
{
|
|
3594
|
+
name: "rect",
|
|
3595
|
+
type: "element",
|
|
3596
|
+
attributes: {
|
|
3597
|
+
class: "pinout-pad",
|
|
3598
|
+
fill: PAD_COLOR4,
|
|
3599
|
+
x: (x - width / 2).toString(),
|
|
3600
|
+
y: (y - height / 2).toString(),
|
|
3601
|
+
width: width.toString(),
|
|
3602
|
+
height: height.toString(),
|
|
3603
|
+
rx: radius.toString(),
|
|
3604
|
+
ry: radius.toString(),
|
|
3605
|
+
"data-layer": pad.layer
|
|
3606
|
+
},
|
|
3607
|
+
value: "",
|
|
3608
|
+
children: []
|
|
3609
|
+
}
|
|
3610
|
+
];
|
|
3611
|
+
}
|
|
3612
|
+
if (pad.shape === "circle") {
|
|
3613
|
+
const radius = pad.radius * Math.abs(transform.a);
|
|
3614
|
+
const [x, y] = applyToPoint32(transform, [pad.x, pad.y]);
|
|
3615
|
+
return [
|
|
3616
|
+
{
|
|
3617
|
+
name: "circle",
|
|
3618
|
+
type: "element",
|
|
3619
|
+
attributes: {
|
|
3620
|
+
class: "pinout-pad",
|
|
3621
|
+
fill: PAD_COLOR4,
|
|
3622
|
+
cx: x.toString(),
|
|
3623
|
+
cy: y.toString(),
|
|
3624
|
+
r: radius.toString(),
|
|
3625
|
+
"data-layer": pad.layer
|
|
3626
|
+
},
|
|
3627
|
+
value: "",
|
|
3628
|
+
children: []
|
|
3629
|
+
}
|
|
3630
|
+
];
|
|
3631
|
+
}
|
|
3632
|
+
if (pad.shape === "polygon") {
|
|
3633
|
+
const points = (pad.points ?? []).map(
|
|
3634
|
+
(point) => applyToPoint32(transform, [point.x, point.y])
|
|
3635
|
+
);
|
|
3636
|
+
return [
|
|
3637
|
+
{
|
|
3638
|
+
name: "polygon",
|
|
3639
|
+
type: "element",
|
|
3640
|
+
attributes: {
|
|
3641
|
+
class: "pinout-pad",
|
|
3642
|
+
fill: PAD_COLOR4,
|
|
3643
|
+
points: points.map((p) => p.join(",")).join(" "),
|
|
3644
|
+
"data-layer": pad.layer
|
|
3645
|
+
},
|
|
3646
|
+
value: "",
|
|
3647
|
+
children: []
|
|
3648
|
+
}
|
|
3649
|
+
];
|
|
3650
|
+
}
|
|
3651
|
+
return [];
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3654
|
+
// lib/pinout/svg-object-fns/create-svg-objects-from-pinout-port.ts
|
|
3655
|
+
import { applyToPoint as applyToPoint33 } from "transformation-matrix";
|
|
3656
|
+
import { calculateElbow } from "calculate-elbow";
|
|
3657
|
+
var LABEL_COLOR = "rgb(255, 255, 255)";
|
|
3658
|
+
var LABEL_BACKGROUND = "rgb(0, 0, 0)";
|
|
3659
|
+
var LINE_COLOR = "rgba(0, 0, 0, 0.6)";
|
|
3660
|
+
function createSvgObjectsFromPinoutPort(pcb_port, ctx) {
|
|
3661
|
+
const label_info = ctx.label_positions.get(pcb_port.pcb_port_id);
|
|
3662
|
+
if (!label_info) return [];
|
|
3663
|
+
const { text: label, aliases, elbow_end, label_pos, edge } = label_info;
|
|
3664
|
+
const [port_x, port_y] = applyToPoint33(ctx.transform, [pcb_port.x, pcb_port.y]);
|
|
3665
|
+
const start_facing_direction = edge === "left" ? "x-" : edge === "right" ? "x+" : edge === "top" ? "y-" : "y+";
|
|
3666
|
+
const end_facing_direction = edge === "left" ? "x+" : edge === "right" ? "x-" : edge === "top" ? "y+" : "y-";
|
|
3667
|
+
const elbow_path = calculateElbow(
|
|
3668
|
+
{
|
|
3669
|
+
x: port_x,
|
|
3670
|
+
y: port_y,
|
|
3671
|
+
facingDirection: start_facing_direction
|
|
3672
|
+
},
|
|
3673
|
+
{
|
|
3674
|
+
x: elbow_end.x,
|
|
3675
|
+
y: elbow_end.y,
|
|
3676
|
+
facingDirection: end_facing_direction
|
|
3677
|
+
},
|
|
3678
|
+
{}
|
|
3679
|
+
);
|
|
3680
|
+
const line_points = [...elbow_path, label_pos].map((p) => `${p.x},${p.y}`).join(" ");
|
|
3681
|
+
const full_label = [label, ...aliases].join(" | ");
|
|
3682
|
+
const fontSize = 11;
|
|
3683
|
+
const textWidth = full_label.length * fontSize * 0.6;
|
|
3684
|
+
const bgPadding = 5;
|
|
3685
|
+
const rectHeight = fontSize + 2 * bgPadding;
|
|
3686
|
+
const rectWidth = textWidth + 2 * bgPadding;
|
|
3687
|
+
const text_y = label_pos.y;
|
|
3688
|
+
let rectX;
|
|
3689
|
+
let text_x;
|
|
3690
|
+
if (edge === "left") {
|
|
3691
|
+
rectX = label_pos.x - rectWidth;
|
|
3692
|
+
text_x = label_pos.x - rectWidth / 2;
|
|
3693
|
+
} else if (edge === "right") {
|
|
3694
|
+
rectX = label_pos.x;
|
|
3695
|
+
text_x = label_pos.x + rectWidth / 2;
|
|
3696
|
+
} else {
|
|
3697
|
+
rectX = label_pos.x - rectWidth / 2;
|
|
3698
|
+
text_x = label_pos.x;
|
|
3699
|
+
}
|
|
3700
|
+
return [
|
|
3701
|
+
{
|
|
3702
|
+
name: "polyline",
|
|
3703
|
+
type: "element",
|
|
3704
|
+
attributes: {
|
|
3705
|
+
points: line_points,
|
|
3706
|
+
stroke: LINE_COLOR,
|
|
3707
|
+
"stroke-width": "1.5",
|
|
3708
|
+
fill: "none"
|
|
3709
|
+
},
|
|
3710
|
+
children: [],
|
|
3711
|
+
value: ""
|
|
3712
|
+
},
|
|
3713
|
+
{
|
|
3714
|
+
name: "rect",
|
|
3715
|
+
type: "element",
|
|
3716
|
+
attributes: {
|
|
3717
|
+
x: rectX.toString(),
|
|
3718
|
+
y: (text_y - rectHeight / 2).toString(),
|
|
3719
|
+
width: rectWidth.toString(),
|
|
3720
|
+
height: rectHeight.toString(),
|
|
3721
|
+
fill: LABEL_BACKGROUND,
|
|
3722
|
+
rx: "8",
|
|
3723
|
+
// More rounded corners
|
|
3724
|
+
ry: "8",
|
|
3725
|
+
stroke: "none"
|
|
3726
|
+
},
|
|
3727
|
+
children: [],
|
|
3728
|
+
value: ""
|
|
3729
|
+
},
|
|
3730
|
+
{
|
|
3731
|
+
name: "text",
|
|
3732
|
+
type: "element",
|
|
3733
|
+
attributes: {
|
|
3734
|
+
x: text_x.toString(),
|
|
3735
|
+
y: text_y.toString(),
|
|
3736
|
+
fill: LABEL_COLOR,
|
|
3737
|
+
"font-size": `${fontSize}px`,
|
|
3738
|
+
"font-family": "Arial, sans-serif",
|
|
3739
|
+
"font-weight": "bold",
|
|
3740
|
+
"text-anchor": "middle",
|
|
3741
|
+
"dominant-baseline": "middle"
|
|
3742
|
+
},
|
|
3743
|
+
children: [
|
|
3744
|
+
{
|
|
3745
|
+
type: "text",
|
|
3746
|
+
value: full_label,
|
|
3747
|
+
name: "",
|
|
3748
|
+
attributes: {},
|
|
3749
|
+
children: []
|
|
3750
|
+
}
|
|
3751
|
+
],
|
|
3752
|
+
value: ""
|
|
3753
|
+
}
|
|
3754
|
+
];
|
|
3755
|
+
}
|
|
3756
|
+
|
|
3757
|
+
// lib/pinout/convert-circuit-json-to-pinout-svg.ts
|
|
3758
|
+
var OBJECT_ORDER3 = [
|
|
3759
|
+
"pcb_board",
|
|
3760
|
+
"pcb_smtpad",
|
|
3761
|
+
"pcb_hole",
|
|
3762
|
+
"pcb_plated_hole",
|
|
3763
|
+
"pcb_component",
|
|
3764
|
+
"pcb_port"
|
|
3765
|
+
];
|
|
3766
|
+
function getPortLabelInfo(port, soup) {
|
|
3767
|
+
const source_port = su6(soup).source_port.get(port.source_port_id);
|
|
3768
|
+
if (!source_port) return null;
|
|
3769
|
+
const eligible_hints = source_port.port_hints?.filter(
|
|
3770
|
+
(h) => !/^\d+$/.test(h) && !["left", "right", "top", "bottom"].includes(h)
|
|
3771
|
+
) ?? [];
|
|
3772
|
+
let label = eligible_hints[0];
|
|
3773
|
+
if (!label) label = source_port.name;
|
|
3774
|
+
if (!label) return null;
|
|
3775
|
+
const aliases = eligible_hints.filter((h) => h !== label);
|
|
3776
|
+
return { text: label, aliases };
|
|
3777
|
+
}
|
|
3778
|
+
function getClosestEdge(port_pos_real, board_bounds) {
|
|
3779
|
+
const dists = {
|
|
3780
|
+
left: port_pos_real.x - board_bounds.minX,
|
|
3781
|
+
right: board_bounds.maxX - port_pos_real.x,
|
|
3782
|
+
top: board_bounds.maxY - port_pos_real.y,
|
|
3783
|
+
bottom: port_pos_real.y - board_bounds.minY
|
|
3784
|
+
};
|
|
3785
|
+
let closest_edge = "left";
|
|
3786
|
+
let min_dist = dists.left;
|
|
3787
|
+
if (dists.right < min_dist) {
|
|
3788
|
+
min_dist = dists.right;
|
|
3789
|
+
closest_edge = "right";
|
|
3790
|
+
}
|
|
3791
|
+
if (dists.top < min_dist) {
|
|
3792
|
+
min_dist = dists.top;
|
|
3793
|
+
closest_edge = "top";
|
|
3794
|
+
}
|
|
3795
|
+
if (dists.bottom < min_dist) {
|
|
3796
|
+
min_dist = dists.bottom;
|
|
3797
|
+
closest_edge = "bottom";
|
|
3798
|
+
}
|
|
3799
|
+
return closest_edge;
|
|
3800
|
+
}
|
|
3801
|
+
function convertCircuitJsonToPinoutSvg(soup, options) {
|
|
3802
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
3803
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
3804
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
3805
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
3806
|
+
for (const item of soup) {
|
|
3807
|
+
if (item.type === "pcb_board") {
|
|
3808
|
+
if ("outline" in item && item.outline && Array.isArray(item.outline) && item.outline.length > 0) {
|
|
3809
|
+
for (const point of item.outline) {
|
|
3810
|
+
minX = Math.min(minX, point.x);
|
|
3811
|
+
minY = Math.min(minY, point.y);
|
|
3812
|
+
maxX = Math.max(maxX, point.x);
|
|
3813
|
+
maxY = Math.max(maxY, point.y);
|
|
3814
|
+
}
|
|
3815
|
+
} else {
|
|
3816
|
+
const center = item.center;
|
|
3817
|
+
const width = item.width || 0;
|
|
3818
|
+
const height = item.height || 0;
|
|
3819
|
+
minX = Math.min(minX, center.x - width / 2);
|
|
3820
|
+
minY = Math.min(minY, center.y - height / 2);
|
|
3821
|
+
maxX = Math.max(maxX, center.x + width / 2);
|
|
3822
|
+
maxY = Math.max(maxY, center.y + height / 2);
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
const padding = 20;
|
|
3827
|
+
const circuitWidth = maxX - minX + 2 * padding;
|
|
3828
|
+
const circuitHeight = maxY - minY + 2 * padding;
|
|
3829
|
+
const svgWidth = options?.width ?? 800;
|
|
3830
|
+
const svgHeight = options?.height ?? 600;
|
|
3831
|
+
const scaleX = svgWidth / circuitWidth;
|
|
3832
|
+
const scaleY = svgHeight / circuitHeight;
|
|
3833
|
+
const scaleFactor = Math.min(scaleX, scaleY);
|
|
3834
|
+
const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
|
|
3835
|
+
const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
|
|
3836
|
+
const transform = compose7(
|
|
3837
|
+
translate7(
|
|
3838
|
+
offsetX - minX * scaleFactor + padding * scaleFactor,
|
|
3839
|
+
svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
|
|
3840
|
+
),
|
|
3841
|
+
scale4(scaleFactor, -scaleFactor)
|
|
3842
|
+
);
|
|
3843
|
+
const board_bounds = { minX, minY, maxX, maxY };
|
|
3844
|
+
const pinout_ports = soup.filter(
|
|
3845
|
+
(elm) => elm.type === "pcb_port" && elm.is_board_pinout
|
|
3846
|
+
);
|
|
3847
|
+
const ports_by_edge = {
|
|
3848
|
+
left: [],
|
|
3849
|
+
right: [],
|
|
3850
|
+
top: [],
|
|
3851
|
+
bottom: []
|
|
3852
|
+
};
|
|
3853
|
+
for (const port of pinout_ports) {
|
|
3854
|
+
const edge = getClosestEdge({ x: port.x, y: port.y }, board_bounds);
|
|
3855
|
+
ports_by_edge[edge].push(port);
|
|
3856
|
+
}
|
|
3857
|
+
const label_positions = /* @__PURE__ */ new Map();
|
|
3858
|
+
const V_SPACING = 20;
|
|
3859
|
+
const STAGGER_OFFSET_MIN = 20;
|
|
3860
|
+
const STAGGER_OFFSET_PER_PIN = 2;
|
|
3861
|
+
const STAGGER_OFFSET_STEP = 15;
|
|
3862
|
+
const ALIGNED_OFFSET_MARGIN = 10;
|
|
3863
|
+
const FONT_SIZE = 11;
|
|
3864
|
+
const BG_PADDING = 5;
|
|
3865
|
+
const LABEL_RECT_HEIGHT = FONT_SIZE + 2 * BG_PADDING;
|
|
3866
|
+
const LABEL_MARGIN = 5;
|
|
3867
|
+
const left_ports = ports_by_edge.left.map((port) => ({
|
|
3868
|
+
port,
|
|
3869
|
+
y: applyToPoint34(transform, [port.x, port.y])[1],
|
|
3870
|
+
label_info: getPortLabelInfo(port, soup)
|
|
3871
|
+
})).filter((p) => p.label_info).sort((a, b) => a.y - b.y);
|
|
3872
|
+
if (left_ports.length > 0) {
|
|
3873
|
+
const board_left_x = applyToPoint34(transform, [board_bounds.minX, 0])[0];
|
|
3874
|
+
const num_labels = left_ports.length;
|
|
3875
|
+
const middle_index = (num_labels - 1) / 2;
|
|
3876
|
+
const stagger_offset_base = STAGGER_OFFSET_MIN + num_labels * STAGGER_OFFSET_PER_PIN;
|
|
3877
|
+
const max_stagger_offset = stagger_offset_base + middle_index * STAGGER_OFFSET_STEP;
|
|
3878
|
+
const aligned_label_offset = max_stagger_offset + ALIGNED_OFFSET_MARGIN;
|
|
3879
|
+
const total_labels_height = num_labels * LABEL_RECT_HEIGHT + Math.max(0, num_labels - 1) * LABEL_MARGIN;
|
|
3880
|
+
let current_y = (svgHeight - total_labels_height) / 2 + LABEL_RECT_HEIGHT / 2;
|
|
3881
|
+
left_ports.forEach(({ port, label_info }, i) => {
|
|
3882
|
+
const dist_from_middle = Math.abs(i - middle_index);
|
|
3883
|
+
const stagger_rank = middle_index - dist_from_middle;
|
|
3884
|
+
const stagger_offset = stagger_offset_base + stagger_rank * STAGGER_OFFSET_STEP;
|
|
3885
|
+
const elbow_end = { x: board_left_x - stagger_offset, y: current_y };
|
|
3886
|
+
const label_pos = { x: board_left_x - aligned_label_offset, y: current_y };
|
|
3887
|
+
label_positions.set(port.pcb_port_id, {
|
|
3888
|
+
text: label_info.text,
|
|
3889
|
+
aliases: label_info.aliases,
|
|
3890
|
+
elbow_end,
|
|
3891
|
+
label_pos,
|
|
3892
|
+
edge: "left"
|
|
3893
|
+
});
|
|
3894
|
+
current_y += LABEL_RECT_HEIGHT + LABEL_MARGIN;
|
|
3895
|
+
});
|
|
3896
|
+
}
|
|
3897
|
+
const right_ports = ports_by_edge.right.map((port) => ({
|
|
3898
|
+
port,
|
|
3899
|
+
y: applyToPoint34(transform, [port.x, port.y])[1],
|
|
3900
|
+
label_info: getPortLabelInfo(port, soup)
|
|
3901
|
+
})).filter((p) => p.label_info).sort((a, b) => a.y - b.y);
|
|
3902
|
+
if (right_ports.length > 0) {
|
|
3903
|
+
const board_right_x = applyToPoint34(transform, [board_bounds.maxX, 0])[0];
|
|
3904
|
+
const num_labels = right_ports.length;
|
|
3905
|
+
const middle_index = (num_labels - 1) / 2;
|
|
3906
|
+
const stagger_offset_base = STAGGER_OFFSET_MIN + num_labels * STAGGER_OFFSET_PER_PIN;
|
|
3907
|
+
const max_stagger_offset = stagger_offset_base + middle_index * STAGGER_OFFSET_STEP;
|
|
3908
|
+
const aligned_label_offset = max_stagger_offset + ALIGNED_OFFSET_MARGIN;
|
|
3909
|
+
const total_labels_height = num_labels * LABEL_RECT_HEIGHT + Math.max(0, num_labels - 1) * LABEL_MARGIN;
|
|
3910
|
+
let current_y = (svgHeight - total_labels_height) / 2 + LABEL_RECT_HEIGHT / 2;
|
|
3911
|
+
right_ports.forEach(({ port, label_info }, i) => {
|
|
3912
|
+
const dist_from_middle = Math.abs(i - middle_index);
|
|
3913
|
+
const stagger_rank = middle_index - dist_from_middle;
|
|
3914
|
+
const stagger_offset = stagger_offset_base + stagger_rank * STAGGER_OFFSET_STEP;
|
|
3915
|
+
const elbow_end = { x: board_right_x + stagger_offset, y: current_y };
|
|
3916
|
+
const label_pos = {
|
|
3917
|
+
x: board_right_x + aligned_label_offset,
|
|
3918
|
+
y: current_y
|
|
3919
|
+
};
|
|
3920
|
+
label_positions.set(port.pcb_port_id, {
|
|
3921
|
+
text: label_info.text,
|
|
3922
|
+
aliases: label_info.aliases,
|
|
3923
|
+
elbow_end,
|
|
3924
|
+
label_pos,
|
|
3925
|
+
edge: "right"
|
|
3926
|
+
});
|
|
3927
|
+
current_y += LABEL_RECT_HEIGHT + LABEL_MARGIN;
|
|
3928
|
+
});
|
|
3929
|
+
}
|
|
3930
|
+
const top_ports = ports_by_edge.top.map((port) => ({
|
|
3931
|
+
port,
|
|
3932
|
+
x: applyToPoint34(transform, [port.x, port.y])[0],
|
|
3933
|
+
label_info: getPortLabelInfo(port, soup)
|
|
3934
|
+
})).filter((p) => p.label_info).sort((a, b) => a.x - b.x);
|
|
3935
|
+
if (top_ports.length > 0) {
|
|
3936
|
+
const board_top_y = applyToPoint34(transform, [0, board_bounds.maxY])[1];
|
|
3937
|
+
const labels_with_widths = top_ports.map((p) => {
|
|
3938
|
+
const label = [p.label_info.text, ...p.label_info.aliases].join(" | ");
|
|
3939
|
+
const textWidth = label.length * FONT_SIZE * 0.6;
|
|
3940
|
+
const rectWidth = textWidth + 2 * BG_PADDING;
|
|
3941
|
+
return { ...p, rectWidth };
|
|
3942
|
+
});
|
|
3943
|
+
const num_labels = labels_with_widths.length;
|
|
3944
|
+
const middle_index = (num_labels - 1) / 2;
|
|
3945
|
+
const stagger_offset_base = STAGGER_OFFSET_MIN + num_labels * STAGGER_OFFSET_PER_PIN;
|
|
3946
|
+
const max_stagger_offset = stagger_offset_base + middle_index * STAGGER_OFFSET_STEP;
|
|
3947
|
+
const aligned_label_offset = max_stagger_offset + ALIGNED_OFFSET_MARGIN;
|
|
3948
|
+
const total_labels_width = labels_with_widths.reduce((sum, l) => sum + l.rectWidth, 0) + Math.max(0, num_labels - 1) * LABEL_MARGIN;
|
|
3949
|
+
let current_x = (svgWidth - total_labels_width) / 2;
|
|
3950
|
+
labels_with_widths.forEach(({ port, label_info, rectWidth }, i) => {
|
|
3951
|
+
const dist_from_middle = Math.abs(i - middle_index);
|
|
3952
|
+
const stagger_rank = middle_index - dist_from_middle;
|
|
3953
|
+
const stagger_offset = stagger_offset_base + stagger_rank * STAGGER_OFFSET_STEP;
|
|
3954
|
+
const label_center_x = current_x + rectWidth / 2;
|
|
3955
|
+
const elbow_end = { x: label_center_x, y: board_top_y - stagger_offset };
|
|
3956
|
+
const label_pos = {
|
|
3957
|
+
x: label_center_x,
|
|
3958
|
+
y: board_top_y - aligned_label_offset
|
|
3959
|
+
};
|
|
3960
|
+
label_positions.set(port.pcb_port_id, {
|
|
3961
|
+
text: label_info.text,
|
|
3962
|
+
aliases: label_info.aliases,
|
|
3963
|
+
elbow_end,
|
|
3964
|
+
label_pos,
|
|
3965
|
+
edge: "top"
|
|
3966
|
+
});
|
|
3967
|
+
current_x += rectWidth + LABEL_MARGIN;
|
|
3968
|
+
});
|
|
3969
|
+
}
|
|
3970
|
+
const bottom_ports = ports_by_edge.bottom.map((port) => ({
|
|
3971
|
+
port,
|
|
3972
|
+
x: applyToPoint34(transform, [port.x, port.y])[0],
|
|
3973
|
+
label_info: getPortLabelInfo(port, soup)
|
|
3974
|
+
})).filter((p) => p.label_info).sort((a, b) => a.x - b.x);
|
|
3975
|
+
if (bottom_ports.length > 0) {
|
|
3976
|
+
const board_bottom_y = applyToPoint34(transform, [0, board_bounds.minY])[1];
|
|
3977
|
+
const labels_with_widths = bottom_ports.map((p) => {
|
|
3978
|
+
const label = [p.label_info.text, ...p.label_info.aliases].join(" | ");
|
|
3979
|
+
const textWidth = label.length * FONT_SIZE * 0.6;
|
|
3980
|
+
const rectWidth = textWidth + 2 * BG_PADDING;
|
|
3981
|
+
return { ...p, rectWidth };
|
|
3982
|
+
});
|
|
3983
|
+
const num_labels = labels_with_widths.length;
|
|
3984
|
+
const middle_index = (num_labels - 1) / 2;
|
|
3985
|
+
const stagger_offset_base = STAGGER_OFFSET_MIN + num_labels * STAGGER_OFFSET_PER_PIN;
|
|
3986
|
+
const max_stagger_offset = stagger_offset_base + middle_index * STAGGER_OFFSET_STEP;
|
|
3987
|
+
const aligned_label_offset = max_stagger_offset + ALIGNED_OFFSET_MARGIN;
|
|
3988
|
+
const total_labels_width = labels_with_widths.reduce((sum, l) => sum + l.rectWidth, 0) + Math.max(0, num_labels - 1) * LABEL_MARGIN;
|
|
3989
|
+
let current_x = (svgWidth - total_labels_width) / 2;
|
|
3990
|
+
labels_with_widths.forEach(({ port, label_info, rectWidth }, i) => {
|
|
3991
|
+
const dist_from_middle = Math.abs(i - middle_index);
|
|
3992
|
+
const stagger_rank = middle_index - dist_from_middle;
|
|
3993
|
+
const stagger_offset = stagger_offset_base + stagger_rank * STAGGER_OFFSET_STEP;
|
|
3994
|
+
const label_center_x = current_x + rectWidth / 2;
|
|
3995
|
+
const elbow_end = {
|
|
3996
|
+
x: label_center_x,
|
|
3997
|
+
y: board_bottom_y + stagger_offset
|
|
3998
|
+
};
|
|
3999
|
+
const label_pos = {
|
|
4000
|
+
x: label_center_x,
|
|
4001
|
+
y: board_bottom_y + aligned_label_offset
|
|
4002
|
+
};
|
|
4003
|
+
label_positions.set(port.pcb_port_id, {
|
|
4004
|
+
text: label_info.text,
|
|
4005
|
+
aliases: label_info.aliases,
|
|
4006
|
+
elbow_end,
|
|
4007
|
+
label_pos,
|
|
4008
|
+
edge: "bottom"
|
|
4009
|
+
});
|
|
4010
|
+
current_x += rectWidth + LABEL_MARGIN;
|
|
4011
|
+
});
|
|
4012
|
+
}
|
|
4013
|
+
const ctx = {
|
|
4014
|
+
transform,
|
|
4015
|
+
soup,
|
|
4016
|
+
board_bounds,
|
|
4017
|
+
label_positions
|
|
4018
|
+
};
|
|
4019
|
+
const svgObjects = soup.sort(
|
|
4020
|
+
(a, b) => (OBJECT_ORDER3.indexOf(a.type) ?? 9999) - (OBJECT_ORDER3.indexOf(b.type) ?? 9999)
|
|
4021
|
+
).flatMap((item) => createSvgObjects3(item, ctx, soup));
|
|
4022
|
+
const softwareUsedString = getSoftwareUsedString(soup);
|
|
4023
|
+
const version = CIRCUIT_TO_SVG_VERSION;
|
|
4024
|
+
const svgObject = {
|
|
4025
|
+
name: "svg",
|
|
4026
|
+
type: "element",
|
|
4027
|
+
attributes: {
|
|
4028
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4029
|
+
width: svgWidth.toString(),
|
|
4030
|
+
height: svgHeight.toString(),
|
|
4031
|
+
...softwareUsedString && {
|
|
4032
|
+
"data-software-used-string": softwareUsedString
|
|
4033
|
+
},
|
|
4034
|
+
...options?.includeVersion && {
|
|
4035
|
+
"data-circuit-to-svg-version": version
|
|
4036
|
+
}
|
|
4037
|
+
},
|
|
4038
|
+
value: "",
|
|
4039
|
+
children: [
|
|
4040
|
+
{
|
|
4041
|
+
name: "rect",
|
|
4042
|
+
type: "element",
|
|
4043
|
+
attributes: {
|
|
4044
|
+
fill: "rgb(255, 255, 255)",
|
|
4045
|
+
x: "0",
|
|
4046
|
+
y: "0",
|
|
4047
|
+
width: svgWidth.toString(),
|
|
4048
|
+
height: svgHeight.toString()
|
|
4049
|
+
},
|
|
4050
|
+
value: "",
|
|
4051
|
+
children: []
|
|
4052
|
+
},
|
|
4053
|
+
...svgObjects
|
|
4054
|
+
].filter((child) => child !== null)
|
|
4055
|
+
};
|
|
4056
|
+
return stringify3(svgObject);
|
|
4057
|
+
}
|
|
4058
|
+
function createSvgObjects3(elm, ctx, soup) {
|
|
4059
|
+
switch (elm.type) {
|
|
4060
|
+
case "pcb_board":
|
|
4061
|
+
return createSvgObjectsFromPinoutBoard(elm, ctx);
|
|
4062
|
+
case "pcb_component":
|
|
4063
|
+
return createSvgObjectsFromPinoutComponent(elm, ctx);
|
|
4064
|
+
case "pcb_smtpad":
|
|
4065
|
+
return createSvgObjectsFromPinoutSmtPad(elm, ctx);
|
|
4066
|
+
case "pcb_hole":
|
|
4067
|
+
return createSvgObjectsFromPinoutHole(elm, ctx);
|
|
4068
|
+
case "pcb_plated_hole":
|
|
4069
|
+
return createSvgObjectsFromPinoutPlatedHole(elm, ctx);
|
|
4070
|
+
case "pcb_port":
|
|
4071
|
+
if (elm.is_board_pinout) {
|
|
4072
|
+
return createSvgObjectsFromPinoutPort(elm, ctx);
|
|
4073
|
+
}
|
|
4074
|
+
return [];
|
|
4075
|
+
default:
|
|
4076
|
+
return [];
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
|
|
3073
4080
|
// lib/utils/colors.ts
|
|
3074
4081
|
var colorMap = {
|
|
3075
4082
|
"3d_viewer": {
|
|
@@ -3310,21 +4317,21 @@ var colorMap = {
|
|
|
3310
4317
|
};
|
|
3311
4318
|
|
|
3312
4319
|
// lib/sch/convert-circuit-json-to-schematic-svg.ts
|
|
3313
|
-
import { stringify as
|
|
4320
|
+
import { stringify as stringify4 } from "svgson";
|
|
3314
4321
|
import {
|
|
3315
4322
|
fromTriangles,
|
|
3316
4323
|
toSVG
|
|
3317
4324
|
} from "transformation-matrix";
|
|
3318
4325
|
|
|
3319
4326
|
// lib/sch/draw-schematic-grid.ts
|
|
3320
|
-
import { applyToPoint as
|
|
4327
|
+
import { applyToPoint as applyToPoint35 } from "transformation-matrix";
|
|
3321
4328
|
function drawSchematicGrid(params) {
|
|
3322
4329
|
const { minX, minY, maxX, maxY } = params.bounds;
|
|
3323
4330
|
const cellSize = params.cellSize ?? 1;
|
|
3324
4331
|
const labelCells = params.labelCells ?? false;
|
|
3325
4332
|
const gridLines = [];
|
|
3326
4333
|
const transformPoint = (x, y) => {
|
|
3327
|
-
const [transformedX, transformedY] =
|
|
4334
|
+
const [transformedX, transformedY] = applyToPoint35(params.transform, [x, y]);
|
|
3328
4335
|
return { x: transformedX, y: transformedY };
|
|
3329
4336
|
};
|
|
3330
4337
|
for (let x = Math.floor(minX); x <= Math.ceil(maxX); x += cellSize) {
|
|
@@ -3405,15 +4412,15 @@ function drawSchematicGrid(params) {
|
|
|
3405
4412
|
}
|
|
3406
4413
|
|
|
3407
4414
|
// lib/sch/draw-schematic-labeled-points.ts
|
|
3408
|
-
import { applyToPoint as
|
|
4415
|
+
import { applyToPoint as applyToPoint36 } from "transformation-matrix";
|
|
3409
4416
|
function drawSchematicLabeledPoints(params) {
|
|
3410
4417
|
const { points, transform } = params;
|
|
3411
4418
|
const labeledPointsGroup = [];
|
|
3412
4419
|
for (const point of points) {
|
|
3413
|
-
const [x1, y1] =
|
|
3414
|
-
const [x2, y2] =
|
|
3415
|
-
const [x3, y3] =
|
|
3416
|
-
const [x4, y4] =
|
|
4420
|
+
const [x1, y1] = applyToPoint36(transform, [point.x - 0.1, point.y - 0.1]);
|
|
4421
|
+
const [x2, y2] = applyToPoint36(transform, [point.x + 0.1, point.y + 0.1]);
|
|
4422
|
+
const [x3, y3] = applyToPoint36(transform, [point.x - 0.1, point.y + 0.1]);
|
|
4423
|
+
const [x4, y4] = applyToPoint36(transform, [point.x + 0.1, point.y - 0.1]);
|
|
3417
4424
|
labeledPointsGroup.push({
|
|
3418
4425
|
name: "path",
|
|
3419
4426
|
type: "element",
|
|
@@ -3424,7 +4431,7 @@ function drawSchematicLabeledPoints(params) {
|
|
|
3424
4431
|
"stroke-opacity": "0.7"
|
|
3425
4432
|
}
|
|
3426
4433
|
});
|
|
3427
|
-
const [labelX, labelY] =
|
|
4434
|
+
const [labelX, labelY] = applyToPoint36(transform, [
|
|
3428
4435
|
point.x + 0.15,
|
|
3429
4436
|
point.y - 0.15
|
|
3430
4437
|
]);
|
|
@@ -4514,12 +5521,12 @@ function getSchematicBoundsFromCircuitJson(soup, padding = 0.5) {
|
|
|
4514
5521
|
}
|
|
4515
5522
|
|
|
4516
5523
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-symbol.ts
|
|
4517
|
-
import { su as
|
|
5524
|
+
import { su as su7 } from "@tscircuit/circuit-json-util";
|
|
4518
5525
|
import { symbols } from "schematic-symbols";
|
|
4519
5526
|
import "svgson";
|
|
4520
5527
|
import {
|
|
4521
|
-
applyToPoint as
|
|
4522
|
-
compose as
|
|
5528
|
+
applyToPoint as applyToPoint38,
|
|
5529
|
+
compose as compose9
|
|
4523
5530
|
} from "transformation-matrix";
|
|
4524
5531
|
|
|
4525
5532
|
// lib/utils/get-sch-stroke-size.ts
|
|
@@ -4589,26 +5596,26 @@ var matchSchPortsToSymbolPorts = ({
|
|
|
4589
5596
|
};
|
|
4590
5597
|
|
|
4591
5598
|
// lib/utils/point-pairs-to-matrix.ts
|
|
4592
|
-
import { compose as
|
|
5599
|
+
import { compose as compose8, scale as scale5, translate as translate8 } from "transformation-matrix";
|
|
4593
5600
|
function pointPairsToMatrix(a1, a2, b1, b2) {
|
|
4594
5601
|
const tx = a2.x - a1.x;
|
|
4595
5602
|
const ty = a2.y - a1.y;
|
|
4596
5603
|
const originalDistance = Math.sqrt((b1.x - a1.x) ** 2 + (b1.y - a1.y) ** 2);
|
|
4597
5604
|
const transformedDistance = Math.sqrt((b2.x - a2.x) ** 2 + (b2.y - a2.y) ** 2);
|
|
4598
5605
|
const a = transformedDistance / originalDistance;
|
|
4599
|
-
const translateMatrix =
|
|
4600
|
-
const scaleMatrix =
|
|
4601
|
-
return
|
|
5606
|
+
const translateMatrix = translate8(tx, ty);
|
|
5607
|
+
const scaleMatrix = scale5(a, a);
|
|
5608
|
+
return compose8(translateMatrix, scaleMatrix);
|
|
4602
5609
|
}
|
|
4603
5610
|
|
|
4604
5611
|
// lib/sch/svg-object-fns/create-svg-error-text.ts
|
|
4605
|
-
import { applyToPoint as
|
|
5612
|
+
import { applyToPoint as applyToPoint37 } from "transformation-matrix";
|
|
4606
5613
|
var createSvgSchErrorText = ({
|
|
4607
5614
|
text,
|
|
4608
5615
|
realCenter,
|
|
4609
5616
|
realToScreenTransform
|
|
4610
5617
|
}) => {
|
|
4611
|
-
const screenCenter =
|
|
5618
|
+
const screenCenter = applyToPoint37(realToScreenTransform, realCenter);
|
|
4612
5619
|
return {
|
|
4613
5620
|
type: "element",
|
|
4614
5621
|
name: "text",
|
|
@@ -4675,10 +5682,10 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
|
4675
5682
|
})
|
|
4676
5683
|
];
|
|
4677
5684
|
}
|
|
4678
|
-
const schPorts =
|
|
5685
|
+
const schPorts = su7(circuitJson).schematic_port.list({
|
|
4679
5686
|
schematic_component_id: schComponent.schematic_component_id
|
|
4680
5687
|
});
|
|
4681
|
-
const srcComponent =
|
|
5688
|
+
const srcComponent = su7(circuitJson).source_component.get(
|
|
4682
5689
|
schComponent.source_component_id
|
|
4683
5690
|
);
|
|
4684
5691
|
const schPortsWithSymbolPorts = matchSchPortsToSymbolPorts({
|
|
@@ -4717,12 +5724,12 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
|
4717
5724
|
minY: Math.min(...paths.flatMap((p) => p.points.map((pt) => pt.y))),
|
|
4718
5725
|
maxY: Math.max(...paths.flatMap((p) => p.points.map((pt) => pt.y)))
|
|
4719
5726
|
};
|
|
4720
|
-
const [screenMinX, screenMinY] =
|
|
4721
|
-
|
|
5727
|
+
const [screenMinX, screenMinY] = applyToPoint38(
|
|
5728
|
+
compose9(realToScreenTransform, transformFromSymbolToReal),
|
|
4722
5729
|
[bounds.minX, bounds.minY]
|
|
4723
5730
|
);
|
|
4724
|
-
const [screenMaxX, screenMaxY] =
|
|
4725
|
-
|
|
5731
|
+
const [screenMaxX, screenMaxY] = applyToPoint38(
|
|
5732
|
+
compose9(realToScreenTransform, transformFromSymbolToReal),
|
|
4726
5733
|
[bounds.maxX, bounds.maxY]
|
|
4727
5734
|
);
|
|
4728
5735
|
const rectHeight = Math.abs(screenMaxY - screenMinY);
|
|
@@ -4750,8 +5757,8 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
|
4750
5757
|
name: "path",
|
|
4751
5758
|
attributes: {
|
|
4752
5759
|
d: points.map((p, i) => {
|
|
4753
|
-
const [x, y] =
|
|
4754
|
-
|
|
5760
|
+
const [x, y] = applyToPoint38(
|
|
5761
|
+
compose9(realToScreenTransform, transformFromSymbolToReal),
|
|
4755
5762
|
[p.x, p.y]
|
|
4756
5763
|
);
|
|
4757
5764
|
return `${i === 0 ? "M" : "L"} ${x} ${y}`;
|
|
@@ -4766,8 +5773,8 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
|
4766
5773
|
});
|
|
4767
5774
|
}
|
|
4768
5775
|
for (const text of texts) {
|
|
4769
|
-
const screenTextPos =
|
|
4770
|
-
|
|
5776
|
+
const screenTextPos = applyToPoint38(
|
|
5777
|
+
compose9(realToScreenTransform, transformFromSymbolToReal),
|
|
4771
5778
|
text
|
|
4772
5779
|
);
|
|
4773
5780
|
let textValue = "";
|
|
@@ -4818,11 +5825,11 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
|
4818
5825
|
});
|
|
4819
5826
|
}
|
|
4820
5827
|
for (const box of boxes) {
|
|
4821
|
-
const screenBoxPos =
|
|
4822
|
-
|
|
5828
|
+
const screenBoxPos = applyToPoint38(
|
|
5829
|
+
compose9(realToScreenTransform, transformFromSymbolToReal),
|
|
4823
5830
|
box
|
|
4824
5831
|
);
|
|
4825
|
-
const symbolToScreenScale =
|
|
5832
|
+
const symbolToScreenScale = compose9(
|
|
4826
5833
|
realToScreenTransform,
|
|
4827
5834
|
transformFromSymbolToReal
|
|
4828
5835
|
).a;
|
|
@@ -4842,8 +5849,8 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
|
4842
5849
|
}
|
|
4843
5850
|
for (const port of symbol.ports) {
|
|
4844
5851
|
if (connectedSymbolPorts.has(port)) continue;
|
|
4845
|
-
const screenPortPos =
|
|
4846
|
-
|
|
5852
|
+
const screenPortPos = applyToPoint38(
|
|
5853
|
+
compose9(realToScreenTransform, transformFromSymbolToReal),
|
|
4847
5854
|
port
|
|
4848
5855
|
);
|
|
4849
5856
|
svgObjects.push({
|
|
@@ -4862,8 +5869,8 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
|
4862
5869
|
});
|
|
4863
5870
|
}
|
|
4864
5871
|
for (const circle of circles) {
|
|
4865
|
-
const screenCirclePos =
|
|
4866
|
-
|
|
5872
|
+
const screenCirclePos = applyToPoint38(
|
|
5873
|
+
compose9(realToScreenTransform, transformFromSymbolToReal),
|
|
4867
5874
|
circle
|
|
4868
5875
|
);
|
|
4869
5876
|
const screenRadius = Math.abs(circle.radius * realToScreenTransform.a);
|
|
@@ -4886,18 +5893,18 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
|
|
|
4886
5893
|
};
|
|
4887
5894
|
|
|
4888
5895
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-box.ts
|
|
4889
|
-
import { su as
|
|
5896
|
+
import { su as su10 } from "@tscircuit/circuit-json-util";
|
|
4890
5897
|
import "schematic-symbols";
|
|
4891
5898
|
import "svgson";
|
|
4892
|
-
import { applyToPoint as
|
|
5899
|
+
import { applyToPoint as applyToPoint44 } from "transformation-matrix";
|
|
4893
5900
|
|
|
4894
5901
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-port-on-box.ts
|
|
4895
5902
|
import "transformation-matrix";
|
|
4896
5903
|
import "@tscircuit/circuit-json-util";
|
|
4897
5904
|
|
|
4898
5905
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-port-box-line.ts
|
|
4899
|
-
import { applyToPoint as
|
|
4900
|
-
import { su as
|
|
5906
|
+
import { applyToPoint as applyToPoint39 } from "transformation-matrix";
|
|
5907
|
+
import { su as su8 } from "@tscircuit/circuit-json-util";
|
|
4901
5908
|
var PIN_CIRCLE_RADIUS_MM = 0.02;
|
|
4902
5909
|
var createArrow = (tip, angle, size, color, strokeWidth) => {
|
|
4903
5910
|
const arrowAngle = Math.PI / 6;
|
|
@@ -4929,7 +5936,7 @@ var createSvgObjectsForSchPortBoxLine = ({
|
|
|
4929
5936
|
circuitJson
|
|
4930
5937
|
}) => {
|
|
4931
5938
|
const svgObjects = [];
|
|
4932
|
-
const srcPort =
|
|
5939
|
+
const srcPort = su8(circuitJson).source_port.get(schPort.source_port_id);
|
|
4933
5940
|
const realEdgePos = {
|
|
4934
5941
|
x: schPort.center.x,
|
|
4935
5942
|
y: schPort.center.y
|
|
@@ -4949,8 +5956,8 @@ var createSvgObjectsForSchPortBoxLine = ({
|
|
|
4949
5956
|
realEdgePos.y += realPinLineLength;
|
|
4950
5957
|
break;
|
|
4951
5958
|
}
|
|
4952
|
-
const screenSchPortPos =
|
|
4953
|
-
const screenRealEdgePos =
|
|
5959
|
+
const screenSchPortPos = applyToPoint39(transform, schPort.center);
|
|
5960
|
+
const screenRealEdgePos = applyToPoint39(transform, realEdgePos);
|
|
4954
5961
|
const realLineEnd = { ...schPort.center };
|
|
4955
5962
|
switch (schPort.side_of_component) {
|
|
4956
5963
|
case "left":
|
|
@@ -4966,7 +5973,7 @@ var createSvgObjectsForSchPortBoxLine = ({
|
|
|
4966
5973
|
realLineEnd.y += PIN_CIRCLE_RADIUS_MM;
|
|
4967
5974
|
break;
|
|
4968
5975
|
}
|
|
4969
|
-
const screenLineEnd =
|
|
5976
|
+
const screenLineEnd = applyToPoint39(transform, realLineEnd);
|
|
4970
5977
|
svgObjects.push({
|
|
4971
5978
|
name: "line",
|
|
4972
5979
|
type: "element",
|
|
@@ -5088,7 +6095,7 @@ var createSvgObjectsForSchPortBoxLine = ({
|
|
|
5088
6095
|
};
|
|
5089
6096
|
|
|
5090
6097
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-port-pin-number-text.ts
|
|
5091
|
-
import { applyToPoint as
|
|
6098
|
+
import { applyToPoint as applyToPoint40 } from "transformation-matrix";
|
|
5092
6099
|
var createSvgObjectsForSchPortPinNumberText = (params) => {
|
|
5093
6100
|
const svgObjects = [];
|
|
5094
6101
|
const { schPort, schComponent, transform, circuitJson } = params;
|
|
@@ -5106,7 +6113,7 @@ var createSvgObjectsForSchPortPinNumberText = (params) => {
|
|
|
5106
6113
|
} else {
|
|
5107
6114
|
realPinNumberPos.y += 0.02;
|
|
5108
6115
|
}
|
|
5109
|
-
const screenPinNumberTextPos =
|
|
6116
|
+
const screenPinNumberTextPos = applyToPoint40(transform, realPinNumberPos);
|
|
5110
6117
|
svgObjects.push({
|
|
5111
6118
|
name: "text",
|
|
5112
6119
|
type: "element",
|
|
@@ -5136,7 +6143,7 @@ var createSvgObjectsForSchPortPinNumberText = (params) => {
|
|
|
5136
6143
|
};
|
|
5137
6144
|
|
|
5138
6145
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-port-pin-label.ts
|
|
5139
|
-
import { applyToPoint as
|
|
6146
|
+
import { applyToPoint as applyToPoint41 } from "transformation-matrix";
|
|
5140
6147
|
var LABEL_DIST_FROM_EDGE_MM = 0.1;
|
|
5141
6148
|
var createSvgObjectsForSchPortPinLabel = (params) => {
|
|
5142
6149
|
const svgObjects = [];
|
|
@@ -5150,7 +6157,7 @@ var createSvgObjectsForSchPortPinLabel = (params) => {
|
|
|
5150
6157
|
const realPinEdgeDistance = schPort.distance_from_component_edge ?? 0.4;
|
|
5151
6158
|
realPinNumberPos.x += vecToEdge.x * (realPinEdgeDistance + LABEL_DIST_FROM_EDGE_MM);
|
|
5152
6159
|
realPinNumberPos.y += vecToEdge.y * (realPinEdgeDistance + LABEL_DIST_FROM_EDGE_MM);
|
|
5153
|
-
const screenPinNumberTextPos =
|
|
6160
|
+
const screenPinNumberTextPos = applyToPoint41(transform, realPinNumberPos);
|
|
5154
6161
|
const label = schPort.display_pin_label ?? schComponent.port_labels?.[`${schPort.pin_number}`];
|
|
5155
6162
|
if (!label) return [];
|
|
5156
6163
|
const isNegated = label.startsWith("N_");
|
|
@@ -5198,13 +6205,13 @@ var createSvgObjectsFromSchPortOnBox = (params) => {
|
|
|
5198
6205
|
};
|
|
5199
6206
|
|
|
5200
6207
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-text.ts
|
|
5201
|
-
import { applyToPoint as
|
|
6208
|
+
import { applyToPoint as applyToPoint43 } from "transformation-matrix";
|
|
5202
6209
|
var createSvgSchText = ({
|
|
5203
6210
|
elm,
|
|
5204
6211
|
transform,
|
|
5205
6212
|
colorMap: colorMap2
|
|
5206
6213
|
}) => {
|
|
5207
|
-
const center =
|
|
6214
|
+
const center = applyToPoint43(transform, elm.position);
|
|
5208
6215
|
const textAnchorMap = {
|
|
5209
6216
|
center: "middle",
|
|
5210
6217
|
center_right: "end",
|
|
@@ -5288,11 +6295,11 @@ var createSvgObjectsFromSchematicComponentWithBox = ({
|
|
|
5288
6295
|
colorMap: colorMap2
|
|
5289
6296
|
}) => {
|
|
5290
6297
|
const svgObjects = [];
|
|
5291
|
-
const componentScreenTopLeft =
|
|
6298
|
+
const componentScreenTopLeft = applyToPoint44(transform, {
|
|
5292
6299
|
x: schComponent.center.x - schComponent.size.width / 2,
|
|
5293
6300
|
y: schComponent.center.y + schComponent.size.height / 2
|
|
5294
6301
|
});
|
|
5295
|
-
const componentScreenBottomRight =
|
|
6302
|
+
const componentScreenBottomRight = applyToPoint44(transform, {
|
|
5296
6303
|
x: schComponent.center.x + schComponent.size.width / 2,
|
|
5297
6304
|
y: schComponent.center.y - schComponent.size.height / 2
|
|
5298
6305
|
});
|
|
@@ -5328,7 +6335,7 @@ var createSvgObjectsFromSchematicComponentWithBox = ({
|
|
|
5328
6335
|
},
|
|
5329
6336
|
children: []
|
|
5330
6337
|
});
|
|
5331
|
-
const schTexts =
|
|
6338
|
+
const schTexts = su10(circuitJson).schematic_text.list();
|
|
5332
6339
|
for (const schText of schTexts) {
|
|
5333
6340
|
if (schText.schematic_component_id === schComponent.schematic_component_id) {
|
|
5334
6341
|
svgObjects.push(
|
|
@@ -5340,7 +6347,7 @@ var createSvgObjectsFromSchematicComponentWithBox = ({
|
|
|
5340
6347
|
);
|
|
5341
6348
|
}
|
|
5342
6349
|
}
|
|
5343
|
-
const schematicPorts =
|
|
6350
|
+
const schematicPorts = su10(circuitJson).schematic_port.list({
|
|
5344
6351
|
schematic_component_id: schComponent.schematic_component_id
|
|
5345
6352
|
});
|
|
5346
6353
|
for (const schPort of schematicPorts) {
|
|
@@ -5359,6 +6366,9 @@ var createSvgObjectsFromSchematicComponentWithBox = ({
|
|
|
5359
6366
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-component.ts
|
|
5360
6367
|
function createSvgObjectsFromSchematicComponent(params) {
|
|
5361
6368
|
const { component } = params;
|
|
6369
|
+
if (component.is_box_with_pins === false) {
|
|
6370
|
+
return [];
|
|
6371
|
+
}
|
|
5362
6372
|
const innerElements = component.symbol_name ? createSvgObjectsFromSchematicComponentWithSymbol(params) : createSvgObjectsFromSchematicComponentWithBox(params);
|
|
5363
6373
|
return [
|
|
5364
6374
|
{
|
|
@@ -5375,13 +6385,13 @@ function createSvgObjectsFromSchematicComponent(params) {
|
|
|
5375
6385
|
}
|
|
5376
6386
|
|
|
5377
6387
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-voltage-probe.ts
|
|
5378
|
-
import { applyToPoint as
|
|
6388
|
+
import { applyToPoint as applyToPoint45 } from "transformation-matrix";
|
|
5379
6389
|
function createSvgObjectsFromSchVoltageProbe({
|
|
5380
6390
|
probe,
|
|
5381
6391
|
transform,
|
|
5382
6392
|
colorMap: colorMap2
|
|
5383
6393
|
}) {
|
|
5384
|
-
const [screenX, screenY] =
|
|
6394
|
+
const [screenX, screenY] = applyToPoint45(transform, [
|
|
5385
6395
|
probe.position.x,
|
|
5386
6396
|
probe.position.y
|
|
5387
6397
|
]);
|
|
@@ -5441,17 +6451,17 @@ function createSvgObjectsFromSchVoltageProbe({
|
|
|
5441
6451
|
}
|
|
5442
6452
|
|
|
5443
6453
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-debug-object.ts
|
|
5444
|
-
import { applyToPoint as
|
|
6454
|
+
import { applyToPoint as applyToPoint46 } from "transformation-matrix";
|
|
5445
6455
|
function createSvgObjectsFromSchDebugObject({
|
|
5446
6456
|
debugObject,
|
|
5447
6457
|
transform
|
|
5448
6458
|
}) {
|
|
5449
6459
|
if (debugObject.shape === "rect") {
|
|
5450
|
-
let [screenLeft, screenTop] =
|
|
6460
|
+
let [screenLeft, screenTop] = applyToPoint46(transform, [
|
|
5451
6461
|
debugObject.center.x - debugObject.size.width / 2,
|
|
5452
6462
|
debugObject.center.y - debugObject.size.height / 2
|
|
5453
6463
|
]);
|
|
5454
|
-
let [screenRight, screenBottom] =
|
|
6464
|
+
let [screenRight, screenBottom] = applyToPoint46(transform, [
|
|
5455
6465
|
debugObject.center.x + debugObject.size.width / 2,
|
|
5456
6466
|
debugObject.center.y + debugObject.size.height / 2
|
|
5457
6467
|
]);
|
|
@@ -5461,7 +6471,7 @@ function createSvgObjectsFromSchDebugObject({
|
|
|
5461
6471
|
];
|
|
5462
6472
|
const width = Math.abs(screenRight - screenLeft);
|
|
5463
6473
|
const height = Math.abs(screenBottom - screenTop);
|
|
5464
|
-
const [screenCenterX, screenCenterY] =
|
|
6474
|
+
const [screenCenterX, screenCenterY] = applyToPoint46(transform, [
|
|
5465
6475
|
debugObject.center.x,
|
|
5466
6476
|
debugObject.center.y
|
|
5467
6477
|
]);
|
|
@@ -5507,11 +6517,11 @@ function createSvgObjectsFromSchDebugObject({
|
|
|
5507
6517
|
];
|
|
5508
6518
|
}
|
|
5509
6519
|
if (debugObject.shape === "line") {
|
|
5510
|
-
const [screenStartX, screenStartY] =
|
|
6520
|
+
const [screenStartX, screenStartY] = applyToPoint46(transform, [
|
|
5511
6521
|
debugObject.start.x,
|
|
5512
6522
|
debugObject.start.y
|
|
5513
6523
|
]);
|
|
5514
|
-
const [screenEndX, screenEndY] =
|
|
6524
|
+
const [screenEndX, screenEndY] = applyToPoint46(transform, [
|
|
5515
6525
|
debugObject.end.x,
|
|
5516
6526
|
debugObject.end.y
|
|
5517
6527
|
]);
|
|
@@ -5561,7 +6571,7 @@ function createSvgObjectsFromSchDebugObject({
|
|
|
5561
6571
|
}
|
|
5562
6572
|
|
|
5563
6573
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts
|
|
5564
|
-
import { applyToPoint as
|
|
6574
|
+
import { applyToPoint as applyToPoint47 } from "transformation-matrix";
|
|
5565
6575
|
function createSchematicTrace({
|
|
5566
6576
|
trace,
|
|
5567
6577
|
transform,
|
|
@@ -5575,11 +6585,11 @@ function createSchematicTrace({
|
|
|
5575
6585
|
for (let edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
|
|
5576
6586
|
const edge = edges[edgeIndex];
|
|
5577
6587
|
if (edge.is_crossing) continue;
|
|
5578
|
-
const [screenFromX, screenFromY] =
|
|
6588
|
+
const [screenFromX, screenFromY] = applyToPoint47(transform, [
|
|
5579
6589
|
edge.from.x,
|
|
5580
6590
|
edge.from.y
|
|
5581
6591
|
]);
|
|
5582
|
-
const [screenToX, screenToY] =
|
|
6592
|
+
const [screenToX, screenToY] = applyToPoint47(transform, [
|
|
5583
6593
|
edge.to.x,
|
|
5584
6594
|
edge.to.y
|
|
5585
6595
|
]);
|
|
@@ -5623,11 +6633,11 @@ function createSchematicTrace({
|
|
|
5623
6633
|
}
|
|
5624
6634
|
for (const edge of edges) {
|
|
5625
6635
|
if (!edge.is_crossing) continue;
|
|
5626
|
-
const [screenFromX, screenFromY] =
|
|
6636
|
+
const [screenFromX, screenFromY] = applyToPoint47(transform, [
|
|
5627
6637
|
edge.from.x,
|
|
5628
6638
|
edge.from.y
|
|
5629
6639
|
]);
|
|
5630
|
-
const [screenToX, screenToY] =
|
|
6640
|
+
const [screenToX, screenToY] = applyToPoint47(transform, [
|
|
5631
6641
|
edge.to.x,
|
|
5632
6642
|
edge.to.y
|
|
5633
6643
|
]);
|
|
@@ -5671,7 +6681,7 @@ function createSchematicTrace({
|
|
|
5671
6681
|
}
|
|
5672
6682
|
if (trace.junctions) {
|
|
5673
6683
|
for (const junction of trace.junctions) {
|
|
5674
|
-
const [screenX, screenY] =
|
|
6684
|
+
const [screenX, screenY] = applyToPoint47(transform, [
|
|
5675
6685
|
junction.x,
|
|
5676
6686
|
junction.y
|
|
5677
6687
|
]);
|
|
@@ -5726,20 +6736,20 @@ function createSchematicTrace({
|
|
|
5726
6736
|
|
|
5727
6737
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label.ts
|
|
5728
6738
|
import {
|
|
5729
|
-
applyToPoint as
|
|
5730
|
-
compose as
|
|
6739
|
+
applyToPoint as applyToPoint49,
|
|
6740
|
+
compose as compose11,
|
|
5731
6741
|
rotate as rotate6,
|
|
5732
|
-
scale as
|
|
5733
|
-
translate as
|
|
6742
|
+
scale as scale7,
|
|
6743
|
+
translate as translate11
|
|
5734
6744
|
} from "transformation-matrix";
|
|
5735
6745
|
|
|
5736
6746
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label-with-symbol.ts
|
|
5737
6747
|
import {
|
|
5738
|
-
applyToPoint as
|
|
5739
|
-
compose as
|
|
6748
|
+
applyToPoint as applyToPoint48,
|
|
6749
|
+
compose as compose10,
|
|
5740
6750
|
rotate as rotate5,
|
|
5741
|
-
scale as
|
|
5742
|
-
translate as
|
|
6751
|
+
scale as scale6,
|
|
6752
|
+
translate as translate10
|
|
5743
6753
|
} from "transformation-matrix";
|
|
5744
6754
|
import { symbols as symbols3 } from "schematic-symbols";
|
|
5745
6755
|
var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
@@ -5810,22 +6820,22 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5810
6820
|
x: symbolBounds.minX,
|
|
5811
6821
|
y: (symbolBounds.minY + symbolBounds.maxY) / 2
|
|
5812
6822
|
};
|
|
5813
|
-
const rotatedSymbolEnd =
|
|
5814
|
-
const symbolToRealTransform =
|
|
5815
|
-
|
|
6823
|
+
const rotatedSymbolEnd = applyToPoint48(rotationMatrix, symbolEndPoint);
|
|
6824
|
+
const symbolToRealTransform = compose10(
|
|
6825
|
+
translate10(
|
|
5816
6826
|
realAnchorPosition.x - rotatedSymbolEnd.x,
|
|
5817
6827
|
realAnchorPosition.y - rotatedSymbolEnd.y
|
|
5818
6828
|
),
|
|
5819
6829
|
rotationMatrix,
|
|
5820
|
-
|
|
6830
|
+
scale6(1)
|
|
5821
6831
|
// Use full symbol size
|
|
5822
6832
|
);
|
|
5823
|
-
const [screenMinX, screenMinY] =
|
|
5824
|
-
|
|
6833
|
+
const [screenMinX, screenMinY] = applyToPoint48(
|
|
6834
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5825
6835
|
[bounds.minX, bounds.minY]
|
|
5826
6836
|
);
|
|
5827
|
-
const [screenMaxX, screenMaxY] =
|
|
5828
|
-
|
|
6837
|
+
const [screenMaxX, screenMaxY] = applyToPoint48(
|
|
6838
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5829
6839
|
[bounds.maxX, bounds.maxY]
|
|
5830
6840
|
);
|
|
5831
6841
|
const rectHeight = Math.abs(screenMaxY - screenMinY);
|
|
@@ -5848,8 +6858,8 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5848
6858
|
});
|
|
5849
6859
|
for (const path of symbolPaths) {
|
|
5850
6860
|
const symbolPath = path.points.map((p, i) => {
|
|
5851
|
-
const [x, y] =
|
|
5852
|
-
|
|
6861
|
+
const [x, y] = applyToPoint48(
|
|
6862
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5853
6863
|
[p.x, p.y]
|
|
5854
6864
|
);
|
|
5855
6865
|
return `${i === 0 ? "M" : "L"} ${x} ${y}`;
|
|
@@ -5869,8 +6879,8 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5869
6879
|
});
|
|
5870
6880
|
}
|
|
5871
6881
|
for (const text of symbolTexts) {
|
|
5872
|
-
const screenTextPos =
|
|
5873
|
-
|
|
6882
|
+
const screenTextPos = applyToPoint48(
|
|
6883
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5874
6884
|
text
|
|
5875
6885
|
);
|
|
5876
6886
|
let textValue = text.text;
|
|
@@ -5879,8 +6889,8 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5879
6889
|
} else if (textValue === "{VAL}") {
|
|
5880
6890
|
textValue = "";
|
|
5881
6891
|
}
|
|
5882
|
-
const
|
|
5883
|
-
const baseOffset =
|
|
6892
|
+
const scale10 = Math.abs(realToScreenTransform.a);
|
|
6893
|
+
const baseOffset = scale10 * 0.1;
|
|
5884
6894
|
const offsetScreenPos = {
|
|
5885
6895
|
x: screenTextPos.x,
|
|
5886
6896
|
y: screenTextPos.y
|
|
@@ -5911,11 +6921,11 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5911
6921
|
});
|
|
5912
6922
|
}
|
|
5913
6923
|
for (const box of symbolBoxes) {
|
|
5914
|
-
const screenBoxPos =
|
|
5915
|
-
|
|
6924
|
+
const screenBoxPos = applyToPoint48(
|
|
6925
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5916
6926
|
box
|
|
5917
6927
|
);
|
|
5918
|
-
const symbolToScreenScale =
|
|
6928
|
+
const symbolToScreenScale = compose10(
|
|
5919
6929
|
realToScreenTransform,
|
|
5920
6930
|
symbolToRealTransform
|
|
5921
6931
|
).a;
|
|
@@ -5934,11 +6944,11 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5934
6944
|
});
|
|
5935
6945
|
}
|
|
5936
6946
|
for (const circle of symbolCircles) {
|
|
5937
|
-
const screenCirclePos =
|
|
5938
|
-
|
|
6947
|
+
const screenCirclePos = applyToPoint48(
|
|
6948
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5939
6949
|
circle
|
|
5940
6950
|
);
|
|
5941
|
-
const symbolToScreenScale =
|
|
6951
|
+
const symbolToScreenScale = compose10(
|
|
5942
6952
|
realToScreenTransform,
|
|
5943
6953
|
symbolToRealTransform
|
|
5944
6954
|
).a;
|
|
@@ -5979,14 +6989,14 @@ var createSvgObjectsForSchNetLabel = ({
|
|
|
5979
6989
|
const fontSizePx = getSchScreenFontSize(realToScreenTransform, "net_label");
|
|
5980
6990
|
const fontSizeMm = getSchMmFontSize("net_label");
|
|
5981
6991
|
const textWidthFSR = estimateTextWidth(labelText || "");
|
|
5982
|
-
const screenCenter =
|
|
6992
|
+
const screenCenter = applyToPoint49(realToScreenTransform, schNetLabel.center);
|
|
5983
6993
|
const realTextGrowthVec = getUnitVectorFromOutsideToEdge(
|
|
5984
6994
|
schNetLabel.anchor_side
|
|
5985
6995
|
);
|
|
5986
6996
|
const screenTextGrowthVec = { ...realTextGrowthVec };
|
|
5987
6997
|
screenTextGrowthVec.y *= -1;
|
|
5988
6998
|
const fullWidthFsr = textWidthFSR + ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_EXTRA_PER_CHARACTER_FSR * labelText.length + END_PADDING_FSR;
|
|
5989
|
-
const screenAnchorPosition = schNetLabel.anchor_position ?
|
|
6999
|
+
const screenAnchorPosition = schNetLabel.anchor_position ? applyToPoint49(realToScreenTransform, schNetLabel.anchor_position) : {
|
|
5990
7000
|
x: screenCenter.x - screenTextGrowthVec.x * fullWidthFsr * fontSizePx / 2,
|
|
5991
7001
|
y: screenCenter.y - screenTextGrowthVec.y * fullWidthFsr * fontSizePx / 2
|
|
5992
7002
|
};
|
|
@@ -6027,11 +7037,11 @@ var createSvgObjectsForSchNetLabel = ({
|
|
|
6027
7037
|
y: -0.6
|
|
6028
7038
|
}
|
|
6029
7039
|
].map(
|
|
6030
|
-
(fontRelativePoint) =>
|
|
6031
|
-
|
|
7040
|
+
(fontRelativePoint) => applyToPoint49(
|
|
7041
|
+
compose11(
|
|
6032
7042
|
realToScreenTransform,
|
|
6033
|
-
|
|
6034
|
-
|
|
7043
|
+
translate11(realAnchorPosition.x, realAnchorPosition.y),
|
|
7044
|
+
scale7(fontSizeMm),
|
|
6035
7045
|
rotate6(pathRotation / 180 * Math.PI)
|
|
6036
7046
|
),
|
|
6037
7047
|
fontRelativePoint
|
|
@@ -6104,17 +7114,17 @@ var createSvgObjectsForSchNetLabel = ({
|
|
|
6104
7114
|
};
|
|
6105
7115
|
|
|
6106
7116
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-box.ts
|
|
6107
|
-
import { applyToPoint as
|
|
7117
|
+
import { applyToPoint as applyToPoint50 } from "transformation-matrix";
|
|
6108
7118
|
var createSvgObjectsFromSchematicBox = ({
|
|
6109
7119
|
schematicBox,
|
|
6110
7120
|
transform,
|
|
6111
7121
|
colorMap: colorMap2
|
|
6112
7122
|
}) => {
|
|
6113
|
-
const topLeft =
|
|
7123
|
+
const topLeft = applyToPoint50(transform, {
|
|
6114
7124
|
x: schematicBox.x,
|
|
6115
7125
|
y: schematicBox.y
|
|
6116
7126
|
});
|
|
6117
|
-
const bottomRight =
|
|
7127
|
+
const bottomRight = applyToPoint50(transform, {
|
|
6118
7128
|
x: schematicBox.x + schematicBox.width,
|
|
6119
7129
|
y: schematicBox.y + schematicBox.height
|
|
6120
7130
|
});
|
|
@@ -6150,7 +7160,7 @@ var createSvgObjectsFromSchematicBox = ({
|
|
|
6150
7160
|
};
|
|
6151
7161
|
|
|
6152
7162
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-table.ts
|
|
6153
|
-
import { applyToPoint as
|
|
7163
|
+
import { applyToPoint as applyToPoint51 } from "transformation-matrix";
|
|
6154
7164
|
var createSvgObjectsFromSchematicTable = ({
|
|
6155
7165
|
schematicTable,
|
|
6156
7166
|
transform,
|
|
@@ -6183,11 +7193,11 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6183
7193
|
const svgObjects = [];
|
|
6184
7194
|
const borderStrokeWidth = border_width * Math.abs(transform.a);
|
|
6185
7195
|
const gridStrokeWidth = getSchStrokeSize(transform);
|
|
6186
|
-
const [screenTopLeftX, screenTopLeftY] =
|
|
7196
|
+
const [screenTopLeftX, screenTopLeftY] = applyToPoint51(transform, [
|
|
6187
7197
|
topLeftX,
|
|
6188
7198
|
topLeftY
|
|
6189
7199
|
]);
|
|
6190
|
-
const [screenBottomRightX, screenBottomRightY] =
|
|
7200
|
+
const [screenBottomRightX, screenBottomRightY] = applyToPoint51(transform, [
|
|
6191
7201
|
topLeftX + totalWidth,
|
|
6192
7202
|
topLeftY - totalHeight
|
|
6193
7203
|
]);
|
|
@@ -6219,8 +7229,8 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6219
7229
|
(cell) => cell.start_column_index <= i && cell.end_column_index > i && cell.start_row_index <= j && cell.end_row_index >= j
|
|
6220
7230
|
);
|
|
6221
7231
|
if (!isMerged) {
|
|
6222
|
-
const start =
|
|
6223
|
-
const end =
|
|
7232
|
+
const start = applyToPoint51(transform, { x: currentX, y: segmentStartY });
|
|
7233
|
+
const end = applyToPoint51(transform, { x: currentX, y: segmentEndY });
|
|
6224
7234
|
svgObjects.push({
|
|
6225
7235
|
name: "line",
|
|
6226
7236
|
type: "element",
|
|
@@ -6249,11 +7259,11 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6249
7259
|
(cell) => cell.start_row_index <= i && cell.end_row_index > i && cell.start_column_index <= j && cell.end_column_index >= j
|
|
6250
7260
|
);
|
|
6251
7261
|
if (!isMerged) {
|
|
6252
|
-
const start =
|
|
7262
|
+
const start = applyToPoint51(transform, {
|
|
6253
7263
|
x: segmentStartX,
|
|
6254
7264
|
y: currentY
|
|
6255
7265
|
});
|
|
6256
|
-
const end =
|
|
7266
|
+
const end = applyToPoint51(transform, { x: segmentEndX, y: currentY });
|
|
6257
7267
|
svgObjects.push({
|
|
6258
7268
|
name: "line",
|
|
6259
7269
|
type: "element",
|
|
@@ -6295,7 +7305,7 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6295
7305
|
} else if (vertical_align === "bottom") {
|
|
6296
7306
|
realTextAnchorPos.y = cellTopLeftY - cellHeight + cell_padding;
|
|
6297
7307
|
}
|
|
6298
|
-
const screenTextAnchorPos =
|
|
7308
|
+
const screenTextAnchorPos = applyToPoint51(transform, realTextAnchorPos);
|
|
6299
7309
|
const fontSize = getSchScreenFontSize(
|
|
6300
7310
|
transform,
|
|
6301
7311
|
"reference_designator",
|
|
@@ -6350,14 +7360,14 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6350
7360
|
};
|
|
6351
7361
|
|
|
6352
7362
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-port-hover.ts
|
|
6353
|
-
import { su as
|
|
6354
|
-
import { applyToPoint as
|
|
7363
|
+
import { su as su11 } from "@tscircuit/circuit-json-util";
|
|
7364
|
+
import { applyToPoint as applyToPoint52 } from "transformation-matrix";
|
|
6355
7365
|
var PIN_CIRCLE_RADIUS_MM2 = 0.02;
|
|
6356
7366
|
var createSvgObjectsForSchPortHover = ({
|
|
6357
7367
|
schPort,
|
|
6358
7368
|
transform
|
|
6359
7369
|
}) => {
|
|
6360
|
-
const screenSchPortPos =
|
|
7370
|
+
const screenSchPortPos = applyToPoint52(transform, schPort.center);
|
|
6361
7371
|
const pinRadiusPx = Math.abs(transform.a) * PIN_CIRCLE_RADIUS_MM2 * 2;
|
|
6362
7372
|
return [
|
|
6363
7373
|
{
|
|
@@ -6391,7 +7401,7 @@ var createSvgObjectsForSchComponentPortHovers = ({
|
|
|
6391
7401
|
transform,
|
|
6392
7402
|
circuitJson
|
|
6393
7403
|
}) => {
|
|
6394
|
-
const schematicPorts =
|
|
7404
|
+
const schematicPorts = su11(circuitJson).schematic_port.list({
|
|
6395
7405
|
schematic_component_id: component.schematic_component_id
|
|
6396
7406
|
});
|
|
6397
7407
|
const svgs = [];
|
|
@@ -6402,14 +7412,14 @@ var createSvgObjectsForSchComponentPortHovers = ({
|
|
|
6402
7412
|
};
|
|
6403
7413
|
|
|
6404
7414
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-line.ts
|
|
6405
|
-
import { applyToPoint as
|
|
7415
|
+
import { applyToPoint as applyToPoint53 } from "transformation-matrix";
|
|
6406
7416
|
function createSvgObjectsFromSchematicLine({
|
|
6407
7417
|
schLine,
|
|
6408
7418
|
transform,
|
|
6409
7419
|
colorMap: colorMap2
|
|
6410
7420
|
}) {
|
|
6411
|
-
const p1 =
|
|
6412
|
-
const p2 =
|
|
7421
|
+
const p1 = applyToPoint53(transform, { x: schLine.x1, y: schLine.y1 });
|
|
7422
|
+
const p2 = applyToPoint53(transform, { x: schLine.x2, y: schLine.y2 });
|
|
6413
7423
|
const strokeWidth = schLine.stroke_width ?? 0.02;
|
|
6414
7424
|
const transformedStrokeWidth = Math.abs(transform.a) * strokeWidth;
|
|
6415
7425
|
return [
|
|
@@ -6438,13 +7448,13 @@ function createSvgObjectsFromSchematicLine({
|
|
|
6438
7448
|
}
|
|
6439
7449
|
|
|
6440
7450
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-circle.ts
|
|
6441
|
-
import { applyToPoint as
|
|
7451
|
+
import { applyToPoint as applyToPoint54 } from "transformation-matrix";
|
|
6442
7452
|
function createSvgObjectsFromSchematicCircle({
|
|
6443
7453
|
schCircle,
|
|
6444
7454
|
transform,
|
|
6445
7455
|
colorMap: colorMap2
|
|
6446
7456
|
}) {
|
|
6447
|
-
const center =
|
|
7457
|
+
const center = applyToPoint54(transform, schCircle.center);
|
|
6448
7458
|
const transformedRadius = Math.abs(transform.a) * schCircle.radius;
|
|
6449
7459
|
const strokeWidth = schCircle.stroke_width ?? 0.02;
|
|
6450
7460
|
const transformedStrokeWidth = Math.abs(transform.a) * strokeWidth;
|
|
@@ -6474,13 +7484,13 @@ function createSvgObjectsFromSchematicCircle({
|
|
|
6474
7484
|
}
|
|
6475
7485
|
|
|
6476
7486
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-rect.ts
|
|
6477
|
-
import { applyToPoint as
|
|
7487
|
+
import { applyToPoint as applyToPoint55 } from "transformation-matrix";
|
|
6478
7488
|
function createSvgObjectsFromSchematicRect({
|
|
6479
7489
|
schRect,
|
|
6480
7490
|
transform,
|
|
6481
7491
|
colorMap: colorMap2
|
|
6482
7492
|
}) {
|
|
6483
|
-
const center =
|
|
7493
|
+
const center = applyToPoint55(transform, schRect.center);
|
|
6484
7494
|
const transformedWidth = Math.abs(transform.a) * schRect.width;
|
|
6485
7495
|
const transformedHeight = Math.abs(transform.d) * schRect.height;
|
|
6486
7496
|
const strokeWidth = schRect.stroke_width ?? 0.02;
|
|
@@ -6516,13 +7526,13 @@ function createSvgObjectsFromSchematicRect({
|
|
|
6516
7526
|
}
|
|
6517
7527
|
|
|
6518
7528
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-arc.ts
|
|
6519
|
-
import { applyToPoint as
|
|
7529
|
+
import { applyToPoint as applyToPoint56 } from "transformation-matrix";
|
|
6520
7530
|
function createSvgObjectsFromSchematicArc({
|
|
6521
7531
|
schArc,
|
|
6522
7532
|
transform,
|
|
6523
7533
|
colorMap: colorMap2
|
|
6524
7534
|
}) {
|
|
6525
|
-
const center =
|
|
7535
|
+
const center = applyToPoint56(transform, schArc.center);
|
|
6526
7536
|
const transformedRadius = Math.abs(transform.a) * schArc.radius;
|
|
6527
7537
|
const strokeWidth = schArc.stroke_width ?? 0.02;
|
|
6528
7538
|
const transformedStrokeWidth = Math.abs(transform.a) * strokeWidth;
|
|
@@ -6862,25 +7872,25 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
|
|
|
6862
7872
|
],
|
|
6863
7873
|
value: ""
|
|
6864
7874
|
};
|
|
6865
|
-
return
|
|
7875
|
+
return stringify4(svgObject);
|
|
6866
7876
|
}
|
|
6867
7877
|
var circuitJsonToSchematicSvg = convertCircuitJsonToSchematicSvg;
|
|
6868
7878
|
|
|
6869
7879
|
// lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
|
|
6870
|
-
import { stringify as
|
|
7880
|
+
import { stringify as stringify5 } from "svgson";
|
|
6871
7881
|
import {
|
|
6872
|
-
applyToPoint as
|
|
6873
|
-
compose as
|
|
6874
|
-
scale as
|
|
6875
|
-
translate as
|
|
7882
|
+
applyToPoint as applyToPoint59,
|
|
7883
|
+
compose as compose14,
|
|
7884
|
+
scale as scale9,
|
|
7885
|
+
translate as translate14
|
|
6876
7886
|
} from "transformation-matrix";
|
|
6877
7887
|
|
|
6878
7888
|
// lib/pcb/svg-object-fns/convert-circuit-json-to-solder-paste-mask.ts
|
|
6879
|
-
import { applyToPoint as
|
|
7889
|
+
import { applyToPoint as applyToPoint58 } from "transformation-matrix";
|
|
6880
7890
|
function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
|
|
6881
7891
|
const { transform, layer: layerFilter } = ctx;
|
|
6882
7892
|
if (layerFilter && solderPaste.layer !== layerFilter) return [];
|
|
6883
|
-
const [x, y] =
|
|
7893
|
+
const [x, y] = applyToPoint58(transform, [solderPaste.x, solderPaste.y]);
|
|
6884
7894
|
if (solderPaste.shape === "rect" || solderPaste.shape === "rotated_rect") {
|
|
6885
7895
|
const width = solderPaste.width * Math.abs(transform.a);
|
|
6886
7896
|
const height = solderPaste.height * Math.abs(transform.d);
|
|
@@ -6955,7 +7965,7 @@ function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
|
|
|
6955
7965
|
}
|
|
6956
7966
|
|
|
6957
7967
|
// lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
|
|
6958
|
-
var
|
|
7968
|
+
var OBJECT_ORDER4 = [
|
|
6959
7969
|
"pcb_board",
|
|
6960
7970
|
"pcb_solder_paste"
|
|
6961
7971
|
];
|
|
@@ -6988,12 +7998,12 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
6988
7998
|
const scaleFactor = Math.min(scaleX, scaleY);
|
|
6989
7999
|
const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
|
|
6990
8000
|
const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
|
|
6991
|
-
const transform =
|
|
6992
|
-
|
|
8001
|
+
const transform = compose14(
|
|
8002
|
+
translate14(
|
|
6993
8003
|
offsetX - minX * scaleFactor + padding * scaleFactor,
|
|
6994
8004
|
svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
|
|
6995
8005
|
),
|
|
6996
|
-
|
|
8006
|
+
scale9(scaleFactor, -scaleFactor)
|
|
6997
8007
|
// Flip in y-direction
|
|
6998
8008
|
);
|
|
6999
8009
|
const ctx = {
|
|
@@ -7002,8 +8012,8 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
7002
8012
|
colorMap: DEFAULT_PCB_COLOR_MAP
|
|
7003
8013
|
};
|
|
7004
8014
|
const svgObjects = filteredCircuitJson.sort(
|
|
7005
|
-
(a, b) => (
|
|
7006
|
-
).flatMap((item) =>
|
|
8015
|
+
(a, b) => (OBJECT_ORDER4.indexOf(b.type) ?? 9999) - (OBJECT_ORDER4.indexOf(a.type) ?? 9999)
|
|
8016
|
+
).flatMap((item) => createSvgObjects4({ elm: item, ctx }));
|
|
7007
8017
|
const softwareUsedString = getSoftwareUsedString(circuitJson);
|
|
7008
8018
|
const version = CIRCUIT_TO_SVG_VERSION;
|
|
7009
8019
|
const svgObject = {
|
|
@@ -7049,7 +8059,7 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
7049
8059
|
].filter((child) => child !== null)
|
|
7050
8060
|
};
|
|
7051
8061
|
try {
|
|
7052
|
-
return
|
|
8062
|
+
return stringify5(svgObject);
|
|
7053
8063
|
} catch (error) {
|
|
7054
8064
|
console.error("Error stringifying SVG object:", error);
|
|
7055
8065
|
throw error;
|
|
@@ -7071,7 +8081,7 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
7071
8081
|
}
|
|
7072
8082
|
}
|
|
7073
8083
|
}
|
|
7074
|
-
function
|
|
8084
|
+
function createSvgObjects4({ elm, ctx }) {
|
|
7075
8085
|
const { transform } = ctx;
|
|
7076
8086
|
switch (elm.type) {
|
|
7077
8087
|
case "pcb_board":
|
|
@@ -7083,8 +8093,8 @@ function createSvgObjects3({ elm, ctx }) {
|
|
|
7083
8093
|
}
|
|
7084
8094
|
}
|
|
7085
8095
|
function createSvgObjectFromPcbBoundary2(transform, minX, minY, maxX, maxY) {
|
|
7086
|
-
const [x1, y1] =
|
|
7087
|
-
const [x2, y2] =
|
|
8096
|
+
const [x1, y1] = applyToPoint59(transform, [minX, minY]);
|
|
8097
|
+
const [x2, y2] = applyToPoint59(transform, [maxX, maxY]);
|
|
7088
8098
|
const width = Math.abs(x2 - x1);
|
|
7089
8099
|
const height = Math.abs(y2 - y1);
|
|
7090
8100
|
const x = Math.min(x1, x2);
|
|
@@ -7112,6 +8122,7 @@ export {
|
|
|
7112
8122
|
circuitJsonToSchematicSvg,
|
|
7113
8123
|
convertCircuitJsonToAssemblySvg,
|
|
7114
8124
|
convertCircuitJsonToPcbSvg,
|
|
8125
|
+
convertCircuitJsonToPinoutSvg,
|
|
7115
8126
|
convertCircuitJsonToSchematicSvg,
|
|
7116
8127
|
convertCircuitJsonToSolderPasteMask,
|
|
7117
8128
|
createSvgObjectsForSchComponentPortHovers,
|