circuit-to-svg 0.0.197 → 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 +1152 -144
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
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: [
|
|
@@ -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) {
|
|
@@ -5378,13 +6385,13 @@ function createSvgObjectsFromSchematicComponent(params) {
|
|
|
5378
6385
|
}
|
|
5379
6386
|
|
|
5380
6387
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-voltage-probe.ts
|
|
5381
|
-
import { applyToPoint as
|
|
6388
|
+
import { applyToPoint as applyToPoint45 } from "transformation-matrix";
|
|
5382
6389
|
function createSvgObjectsFromSchVoltageProbe({
|
|
5383
6390
|
probe,
|
|
5384
6391
|
transform,
|
|
5385
6392
|
colorMap: colorMap2
|
|
5386
6393
|
}) {
|
|
5387
|
-
const [screenX, screenY] =
|
|
6394
|
+
const [screenX, screenY] = applyToPoint45(transform, [
|
|
5388
6395
|
probe.position.x,
|
|
5389
6396
|
probe.position.y
|
|
5390
6397
|
]);
|
|
@@ -5444,17 +6451,17 @@ function createSvgObjectsFromSchVoltageProbe({
|
|
|
5444
6451
|
}
|
|
5445
6452
|
|
|
5446
6453
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-debug-object.ts
|
|
5447
|
-
import { applyToPoint as
|
|
6454
|
+
import { applyToPoint as applyToPoint46 } from "transformation-matrix";
|
|
5448
6455
|
function createSvgObjectsFromSchDebugObject({
|
|
5449
6456
|
debugObject,
|
|
5450
6457
|
transform
|
|
5451
6458
|
}) {
|
|
5452
6459
|
if (debugObject.shape === "rect") {
|
|
5453
|
-
let [screenLeft, screenTop] =
|
|
6460
|
+
let [screenLeft, screenTop] = applyToPoint46(transform, [
|
|
5454
6461
|
debugObject.center.x - debugObject.size.width / 2,
|
|
5455
6462
|
debugObject.center.y - debugObject.size.height / 2
|
|
5456
6463
|
]);
|
|
5457
|
-
let [screenRight, screenBottom] =
|
|
6464
|
+
let [screenRight, screenBottom] = applyToPoint46(transform, [
|
|
5458
6465
|
debugObject.center.x + debugObject.size.width / 2,
|
|
5459
6466
|
debugObject.center.y + debugObject.size.height / 2
|
|
5460
6467
|
]);
|
|
@@ -5464,7 +6471,7 @@ function createSvgObjectsFromSchDebugObject({
|
|
|
5464
6471
|
];
|
|
5465
6472
|
const width = Math.abs(screenRight - screenLeft);
|
|
5466
6473
|
const height = Math.abs(screenBottom - screenTop);
|
|
5467
|
-
const [screenCenterX, screenCenterY] =
|
|
6474
|
+
const [screenCenterX, screenCenterY] = applyToPoint46(transform, [
|
|
5468
6475
|
debugObject.center.x,
|
|
5469
6476
|
debugObject.center.y
|
|
5470
6477
|
]);
|
|
@@ -5510,11 +6517,11 @@ function createSvgObjectsFromSchDebugObject({
|
|
|
5510
6517
|
];
|
|
5511
6518
|
}
|
|
5512
6519
|
if (debugObject.shape === "line") {
|
|
5513
|
-
const [screenStartX, screenStartY] =
|
|
6520
|
+
const [screenStartX, screenStartY] = applyToPoint46(transform, [
|
|
5514
6521
|
debugObject.start.x,
|
|
5515
6522
|
debugObject.start.y
|
|
5516
6523
|
]);
|
|
5517
|
-
const [screenEndX, screenEndY] =
|
|
6524
|
+
const [screenEndX, screenEndY] = applyToPoint46(transform, [
|
|
5518
6525
|
debugObject.end.x,
|
|
5519
6526
|
debugObject.end.y
|
|
5520
6527
|
]);
|
|
@@ -5564,7 +6571,7 @@ function createSvgObjectsFromSchDebugObject({
|
|
|
5564
6571
|
}
|
|
5565
6572
|
|
|
5566
6573
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts
|
|
5567
|
-
import { applyToPoint as
|
|
6574
|
+
import { applyToPoint as applyToPoint47 } from "transformation-matrix";
|
|
5568
6575
|
function createSchematicTrace({
|
|
5569
6576
|
trace,
|
|
5570
6577
|
transform,
|
|
@@ -5578,11 +6585,11 @@ function createSchematicTrace({
|
|
|
5578
6585
|
for (let edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
|
|
5579
6586
|
const edge = edges[edgeIndex];
|
|
5580
6587
|
if (edge.is_crossing) continue;
|
|
5581
|
-
const [screenFromX, screenFromY] =
|
|
6588
|
+
const [screenFromX, screenFromY] = applyToPoint47(transform, [
|
|
5582
6589
|
edge.from.x,
|
|
5583
6590
|
edge.from.y
|
|
5584
6591
|
]);
|
|
5585
|
-
const [screenToX, screenToY] =
|
|
6592
|
+
const [screenToX, screenToY] = applyToPoint47(transform, [
|
|
5586
6593
|
edge.to.x,
|
|
5587
6594
|
edge.to.y
|
|
5588
6595
|
]);
|
|
@@ -5626,11 +6633,11 @@ function createSchematicTrace({
|
|
|
5626
6633
|
}
|
|
5627
6634
|
for (const edge of edges) {
|
|
5628
6635
|
if (!edge.is_crossing) continue;
|
|
5629
|
-
const [screenFromX, screenFromY] =
|
|
6636
|
+
const [screenFromX, screenFromY] = applyToPoint47(transform, [
|
|
5630
6637
|
edge.from.x,
|
|
5631
6638
|
edge.from.y
|
|
5632
6639
|
]);
|
|
5633
|
-
const [screenToX, screenToY] =
|
|
6640
|
+
const [screenToX, screenToY] = applyToPoint47(transform, [
|
|
5634
6641
|
edge.to.x,
|
|
5635
6642
|
edge.to.y
|
|
5636
6643
|
]);
|
|
@@ -5674,7 +6681,7 @@ function createSchematicTrace({
|
|
|
5674
6681
|
}
|
|
5675
6682
|
if (trace.junctions) {
|
|
5676
6683
|
for (const junction of trace.junctions) {
|
|
5677
|
-
const [screenX, screenY] =
|
|
6684
|
+
const [screenX, screenY] = applyToPoint47(transform, [
|
|
5678
6685
|
junction.x,
|
|
5679
6686
|
junction.y
|
|
5680
6687
|
]);
|
|
@@ -5729,20 +6736,20 @@ function createSchematicTrace({
|
|
|
5729
6736
|
|
|
5730
6737
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label.ts
|
|
5731
6738
|
import {
|
|
5732
|
-
applyToPoint as
|
|
5733
|
-
compose as
|
|
6739
|
+
applyToPoint as applyToPoint49,
|
|
6740
|
+
compose as compose11,
|
|
5734
6741
|
rotate as rotate6,
|
|
5735
|
-
scale as
|
|
5736
|
-
translate as
|
|
6742
|
+
scale as scale7,
|
|
6743
|
+
translate as translate11
|
|
5737
6744
|
} from "transformation-matrix";
|
|
5738
6745
|
|
|
5739
6746
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label-with-symbol.ts
|
|
5740
6747
|
import {
|
|
5741
|
-
applyToPoint as
|
|
5742
|
-
compose as
|
|
6748
|
+
applyToPoint as applyToPoint48,
|
|
6749
|
+
compose as compose10,
|
|
5743
6750
|
rotate as rotate5,
|
|
5744
|
-
scale as
|
|
5745
|
-
translate as
|
|
6751
|
+
scale as scale6,
|
|
6752
|
+
translate as translate10
|
|
5746
6753
|
} from "transformation-matrix";
|
|
5747
6754
|
import { symbols as symbols3 } from "schematic-symbols";
|
|
5748
6755
|
var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
@@ -5813,22 +6820,22 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5813
6820
|
x: symbolBounds.minX,
|
|
5814
6821
|
y: (symbolBounds.minY + symbolBounds.maxY) / 2
|
|
5815
6822
|
};
|
|
5816
|
-
const rotatedSymbolEnd =
|
|
5817
|
-
const symbolToRealTransform =
|
|
5818
|
-
|
|
6823
|
+
const rotatedSymbolEnd = applyToPoint48(rotationMatrix, symbolEndPoint);
|
|
6824
|
+
const symbolToRealTransform = compose10(
|
|
6825
|
+
translate10(
|
|
5819
6826
|
realAnchorPosition.x - rotatedSymbolEnd.x,
|
|
5820
6827
|
realAnchorPosition.y - rotatedSymbolEnd.y
|
|
5821
6828
|
),
|
|
5822
6829
|
rotationMatrix,
|
|
5823
|
-
|
|
6830
|
+
scale6(1)
|
|
5824
6831
|
// Use full symbol size
|
|
5825
6832
|
);
|
|
5826
|
-
const [screenMinX, screenMinY] =
|
|
5827
|
-
|
|
6833
|
+
const [screenMinX, screenMinY] = applyToPoint48(
|
|
6834
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5828
6835
|
[bounds.minX, bounds.minY]
|
|
5829
6836
|
);
|
|
5830
|
-
const [screenMaxX, screenMaxY] =
|
|
5831
|
-
|
|
6837
|
+
const [screenMaxX, screenMaxY] = applyToPoint48(
|
|
6838
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5832
6839
|
[bounds.maxX, bounds.maxY]
|
|
5833
6840
|
);
|
|
5834
6841
|
const rectHeight = Math.abs(screenMaxY - screenMinY);
|
|
@@ -5851,8 +6858,8 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5851
6858
|
});
|
|
5852
6859
|
for (const path of symbolPaths) {
|
|
5853
6860
|
const symbolPath = path.points.map((p, i) => {
|
|
5854
|
-
const [x, y] =
|
|
5855
|
-
|
|
6861
|
+
const [x, y] = applyToPoint48(
|
|
6862
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5856
6863
|
[p.x, p.y]
|
|
5857
6864
|
);
|
|
5858
6865
|
return `${i === 0 ? "M" : "L"} ${x} ${y}`;
|
|
@@ -5872,8 +6879,8 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5872
6879
|
});
|
|
5873
6880
|
}
|
|
5874
6881
|
for (const text of symbolTexts) {
|
|
5875
|
-
const screenTextPos =
|
|
5876
|
-
|
|
6882
|
+
const screenTextPos = applyToPoint48(
|
|
6883
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5877
6884
|
text
|
|
5878
6885
|
);
|
|
5879
6886
|
let textValue = text.text;
|
|
@@ -5882,8 +6889,8 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5882
6889
|
} else if (textValue === "{VAL}") {
|
|
5883
6890
|
textValue = "";
|
|
5884
6891
|
}
|
|
5885
|
-
const
|
|
5886
|
-
const baseOffset =
|
|
6892
|
+
const scale10 = Math.abs(realToScreenTransform.a);
|
|
6893
|
+
const baseOffset = scale10 * 0.1;
|
|
5887
6894
|
const offsetScreenPos = {
|
|
5888
6895
|
x: screenTextPos.x,
|
|
5889
6896
|
y: screenTextPos.y
|
|
@@ -5914,11 +6921,11 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5914
6921
|
});
|
|
5915
6922
|
}
|
|
5916
6923
|
for (const box of symbolBoxes) {
|
|
5917
|
-
const screenBoxPos =
|
|
5918
|
-
|
|
6924
|
+
const screenBoxPos = applyToPoint48(
|
|
6925
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5919
6926
|
box
|
|
5920
6927
|
);
|
|
5921
|
-
const symbolToScreenScale =
|
|
6928
|
+
const symbolToScreenScale = compose10(
|
|
5922
6929
|
realToScreenTransform,
|
|
5923
6930
|
symbolToRealTransform
|
|
5924
6931
|
).a;
|
|
@@ -5937,11 +6944,11 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
5937
6944
|
});
|
|
5938
6945
|
}
|
|
5939
6946
|
for (const circle of symbolCircles) {
|
|
5940
|
-
const screenCirclePos =
|
|
5941
|
-
|
|
6947
|
+
const screenCirclePos = applyToPoint48(
|
|
6948
|
+
compose10(realToScreenTransform, symbolToRealTransform),
|
|
5942
6949
|
circle
|
|
5943
6950
|
);
|
|
5944
|
-
const symbolToScreenScale =
|
|
6951
|
+
const symbolToScreenScale = compose10(
|
|
5945
6952
|
realToScreenTransform,
|
|
5946
6953
|
symbolToRealTransform
|
|
5947
6954
|
).a;
|
|
@@ -5982,14 +6989,14 @@ var createSvgObjectsForSchNetLabel = ({
|
|
|
5982
6989
|
const fontSizePx = getSchScreenFontSize(realToScreenTransform, "net_label");
|
|
5983
6990
|
const fontSizeMm = getSchMmFontSize("net_label");
|
|
5984
6991
|
const textWidthFSR = estimateTextWidth(labelText || "");
|
|
5985
|
-
const screenCenter =
|
|
6992
|
+
const screenCenter = applyToPoint49(realToScreenTransform, schNetLabel.center);
|
|
5986
6993
|
const realTextGrowthVec = getUnitVectorFromOutsideToEdge(
|
|
5987
6994
|
schNetLabel.anchor_side
|
|
5988
6995
|
);
|
|
5989
6996
|
const screenTextGrowthVec = { ...realTextGrowthVec };
|
|
5990
6997
|
screenTextGrowthVec.y *= -1;
|
|
5991
6998
|
const fullWidthFsr = textWidthFSR + ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_EXTRA_PER_CHARACTER_FSR * labelText.length + END_PADDING_FSR;
|
|
5992
|
-
const screenAnchorPosition = schNetLabel.anchor_position ?
|
|
6999
|
+
const screenAnchorPosition = schNetLabel.anchor_position ? applyToPoint49(realToScreenTransform, schNetLabel.anchor_position) : {
|
|
5993
7000
|
x: screenCenter.x - screenTextGrowthVec.x * fullWidthFsr * fontSizePx / 2,
|
|
5994
7001
|
y: screenCenter.y - screenTextGrowthVec.y * fullWidthFsr * fontSizePx / 2
|
|
5995
7002
|
};
|
|
@@ -6030,11 +7037,11 @@ var createSvgObjectsForSchNetLabel = ({
|
|
|
6030
7037
|
y: -0.6
|
|
6031
7038
|
}
|
|
6032
7039
|
].map(
|
|
6033
|
-
(fontRelativePoint) =>
|
|
6034
|
-
|
|
7040
|
+
(fontRelativePoint) => applyToPoint49(
|
|
7041
|
+
compose11(
|
|
6035
7042
|
realToScreenTransform,
|
|
6036
|
-
|
|
6037
|
-
|
|
7043
|
+
translate11(realAnchorPosition.x, realAnchorPosition.y),
|
|
7044
|
+
scale7(fontSizeMm),
|
|
6038
7045
|
rotate6(pathRotation / 180 * Math.PI)
|
|
6039
7046
|
),
|
|
6040
7047
|
fontRelativePoint
|
|
@@ -6107,17 +7114,17 @@ var createSvgObjectsForSchNetLabel = ({
|
|
|
6107
7114
|
};
|
|
6108
7115
|
|
|
6109
7116
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-box.ts
|
|
6110
|
-
import { applyToPoint as
|
|
7117
|
+
import { applyToPoint as applyToPoint50 } from "transformation-matrix";
|
|
6111
7118
|
var createSvgObjectsFromSchematicBox = ({
|
|
6112
7119
|
schematicBox,
|
|
6113
7120
|
transform,
|
|
6114
7121
|
colorMap: colorMap2
|
|
6115
7122
|
}) => {
|
|
6116
|
-
const topLeft =
|
|
7123
|
+
const topLeft = applyToPoint50(transform, {
|
|
6117
7124
|
x: schematicBox.x,
|
|
6118
7125
|
y: schematicBox.y
|
|
6119
7126
|
});
|
|
6120
|
-
const bottomRight =
|
|
7127
|
+
const bottomRight = applyToPoint50(transform, {
|
|
6121
7128
|
x: schematicBox.x + schematicBox.width,
|
|
6122
7129
|
y: schematicBox.y + schematicBox.height
|
|
6123
7130
|
});
|
|
@@ -6153,7 +7160,7 @@ var createSvgObjectsFromSchematicBox = ({
|
|
|
6153
7160
|
};
|
|
6154
7161
|
|
|
6155
7162
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-table.ts
|
|
6156
|
-
import { applyToPoint as
|
|
7163
|
+
import { applyToPoint as applyToPoint51 } from "transformation-matrix";
|
|
6157
7164
|
var createSvgObjectsFromSchematicTable = ({
|
|
6158
7165
|
schematicTable,
|
|
6159
7166
|
transform,
|
|
@@ -6186,11 +7193,11 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6186
7193
|
const svgObjects = [];
|
|
6187
7194
|
const borderStrokeWidth = border_width * Math.abs(transform.a);
|
|
6188
7195
|
const gridStrokeWidth = getSchStrokeSize(transform);
|
|
6189
|
-
const [screenTopLeftX, screenTopLeftY] =
|
|
7196
|
+
const [screenTopLeftX, screenTopLeftY] = applyToPoint51(transform, [
|
|
6190
7197
|
topLeftX,
|
|
6191
7198
|
topLeftY
|
|
6192
7199
|
]);
|
|
6193
|
-
const [screenBottomRightX, screenBottomRightY] =
|
|
7200
|
+
const [screenBottomRightX, screenBottomRightY] = applyToPoint51(transform, [
|
|
6194
7201
|
topLeftX + totalWidth,
|
|
6195
7202
|
topLeftY - totalHeight
|
|
6196
7203
|
]);
|
|
@@ -6222,8 +7229,8 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6222
7229
|
(cell) => cell.start_column_index <= i && cell.end_column_index > i && cell.start_row_index <= j && cell.end_row_index >= j
|
|
6223
7230
|
);
|
|
6224
7231
|
if (!isMerged) {
|
|
6225
|
-
const start =
|
|
6226
|
-
const end =
|
|
7232
|
+
const start = applyToPoint51(transform, { x: currentX, y: segmentStartY });
|
|
7233
|
+
const end = applyToPoint51(transform, { x: currentX, y: segmentEndY });
|
|
6227
7234
|
svgObjects.push({
|
|
6228
7235
|
name: "line",
|
|
6229
7236
|
type: "element",
|
|
@@ -6252,11 +7259,11 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6252
7259
|
(cell) => cell.start_row_index <= i && cell.end_row_index > i && cell.start_column_index <= j && cell.end_column_index >= j
|
|
6253
7260
|
);
|
|
6254
7261
|
if (!isMerged) {
|
|
6255
|
-
const start =
|
|
7262
|
+
const start = applyToPoint51(transform, {
|
|
6256
7263
|
x: segmentStartX,
|
|
6257
7264
|
y: currentY
|
|
6258
7265
|
});
|
|
6259
|
-
const end =
|
|
7266
|
+
const end = applyToPoint51(transform, { x: segmentEndX, y: currentY });
|
|
6260
7267
|
svgObjects.push({
|
|
6261
7268
|
name: "line",
|
|
6262
7269
|
type: "element",
|
|
@@ -6298,7 +7305,7 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6298
7305
|
} else if (vertical_align === "bottom") {
|
|
6299
7306
|
realTextAnchorPos.y = cellTopLeftY - cellHeight + cell_padding;
|
|
6300
7307
|
}
|
|
6301
|
-
const screenTextAnchorPos =
|
|
7308
|
+
const screenTextAnchorPos = applyToPoint51(transform, realTextAnchorPos);
|
|
6302
7309
|
const fontSize = getSchScreenFontSize(
|
|
6303
7310
|
transform,
|
|
6304
7311
|
"reference_designator",
|
|
@@ -6353,14 +7360,14 @@ var createSvgObjectsFromSchematicTable = ({
|
|
|
6353
7360
|
};
|
|
6354
7361
|
|
|
6355
7362
|
// lib/sch/svg-object-fns/create-svg-objects-for-sch-port-hover.ts
|
|
6356
|
-
import { su as
|
|
6357
|
-
import { applyToPoint as
|
|
7363
|
+
import { su as su11 } from "@tscircuit/circuit-json-util";
|
|
7364
|
+
import { applyToPoint as applyToPoint52 } from "transformation-matrix";
|
|
6358
7365
|
var PIN_CIRCLE_RADIUS_MM2 = 0.02;
|
|
6359
7366
|
var createSvgObjectsForSchPortHover = ({
|
|
6360
7367
|
schPort,
|
|
6361
7368
|
transform
|
|
6362
7369
|
}) => {
|
|
6363
|
-
const screenSchPortPos =
|
|
7370
|
+
const screenSchPortPos = applyToPoint52(transform, schPort.center);
|
|
6364
7371
|
const pinRadiusPx = Math.abs(transform.a) * PIN_CIRCLE_RADIUS_MM2 * 2;
|
|
6365
7372
|
return [
|
|
6366
7373
|
{
|
|
@@ -6394,7 +7401,7 @@ var createSvgObjectsForSchComponentPortHovers = ({
|
|
|
6394
7401
|
transform,
|
|
6395
7402
|
circuitJson
|
|
6396
7403
|
}) => {
|
|
6397
|
-
const schematicPorts =
|
|
7404
|
+
const schematicPorts = su11(circuitJson).schematic_port.list({
|
|
6398
7405
|
schematic_component_id: component.schematic_component_id
|
|
6399
7406
|
});
|
|
6400
7407
|
const svgs = [];
|
|
@@ -6405,14 +7412,14 @@ var createSvgObjectsForSchComponentPortHovers = ({
|
|
|
6405
7412
|
};
|
|
6406
7413
|
|
|
6407
7414
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-line.ts
|
|
6408
|
-
import { applyToPoint as
|
|
7415
|
+
import { applyToPoint as applyToPoint53 } from "transformation-matrix";
|
|
6409
7416
|
function createSvgObjectsFromSchematicLine({
|
|
6410
7417
|
schLine,
|
|
6411
7418
|
transform,
|
|
6412
7419
|
colorMap: colorMap2
|
|
6413
7420
|
}) {
|
|
6414
|
-
const p1 =
|
|
6415
|
-
const p2 =
|
|
7421
|
+
const p1 = applyToPoint53(transform, { x: schLine.x1, y: schLine.y1 });
|
|
7422
|
+
const p2 = applyToPoint53(transform, { x: schLine.x2, y: schLine.y2 });
|
|
6416
7423
|
const strokeWidth = schLine.stroke_width ?? 0.02;
|
|
6417
7424
|
const transformedStrokeWidth = Math.abs(transform.a) * strokeWidth;
|
|
6418
7425
|
return [
|
|
@@ -6441,13 +7448,13 @@ function createSvgObjectsFromSchematicLine({
|
|
|
6441
7448
|
}
|
|
6442
7449
|
|
|
6443
7450
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-circle.ts
|
|
6444
|
-
import { applyToPoint as
|
|
7451
|
+
import { applyToPoint as applyToPoint54 } from "transformation-matrix";
|
|
6445
7452
|
function createSvgObjectsFromSchematicCircle({
|
|
6446
7453
|
schCircle,
|
|
6447
7454
|
transform,
|
|
6448
7455
|
colorMap: colorMap2
|
|
6449
7456
|
}) {
|
|
6450
|
-
const center =
|
|
7457
|
+
const center = applyToPoint54(transform, schCircle.center);
|
|
6451
7458
|
const transformedRadius = Math.abs(transform.a) * schCircle.radius;
|
|
6452
7459
|
const strokeWidth = schCircle.stroke_width ?? 0.02;
|
|
6453
7460
|
const transformedStrokeWidth = Math.abs(transform.a) * strokeWidth;
|
|
@@ -6477,13 +7484,13 @@ function createSvgObjectsFromSchematicCircle({
|
|
|
6477
7484
|
}
|
|
6478
7485
|
|
|
6479
7486
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-rect.ts
|
|
6480
|
-
import { applyToPoint as
|
|
7487
|
+
import { applyToPoint as applyToPoint55 } from "transformation-matrix";
|
|
6481
7488
|
function createSvgObjectsFromSchematicRect({
|
|
6482
7489
|
schRect,
|
|
6483
7490
|
transform,
|
|
6484
7491
|
colorMap: colorMap2
|
|
6485
7492
|
}) {
|
|
6486
|
-
const center =
|
|
7493
|
+
const center = applyToPoint55(transform, schRect.center);
|
|
6487
7494
|
const transformedWidth = Math.abs(transform.a) * schRect.width;
|
|
6488
7495
|
const transformedHeight = Math.abs(transform.d) * schRect.height;
|
|
6489
7496
|
const strokeWidth = schRect.stroke_width ?? 0.02;
|
|
@@ -6519,13 +7526,13 @@ function createSvgObjectsFromSchematicRect({
|
|
|
6519
7526
|
}
|
|
6520
7527
|
|
|
6521
7528
|
// lib/sch/svg-object-fns/create-svg-objects-from-sch-arc.ts
|
|
6522
|
-
import { applyToPoint as
|
|
7529
|
+
import { applyToPoint as applyToPoint56 } from "transformation-matrix";
|
|
6523
7530
|
function createSvgObjectsFromSchematicArc({
|
|
6524
7531
|
schArc,
|
|
6525
7532
|
transform,
|
|
6526
7533
|
colorMap: colorMap2
|
|
6527
7534
|
}) {
|
|
6528
|
-
const center =
|
|
7535
|
+
const center = applyToPoint56(transform, schArc.center);
|
|
6529
7536
|
const transformedRadius = Math.abs(transform.a) * schArc.radius;
|
|
6530
7537
|
const strokeWidth = schArc.stroke_width ?? 0.02;
|
|
6531
7538
|
const transformedStrokeWidth = Math.abs(transform.a) * strokeWidth;
|
|
@@ -6865,25 +7872,25 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
|
|
|
6865
7872
|
],
|
|
6866
7873
|
value: ""
|
|
6867
7874
|
};
|
|
6868
|
-
return
|
|
7875
|
+
return stringify4(svgObject);
|
|
6869
7876
|
}
|
|
6870
7877
|
var circuitJsonToSchematicSvg = convertCircuitJsonToSchematicSvg;
|
|
6871
7878
|
|
|
6872
7879
|
// lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
|
|
6873
|
-
import { stringify as
|
|
7880
|
+
import { stringify as stringify5 } from "svgson";
|
|
6874
7881
|
import {
|
|
6875
|
-
applyToPoint as
|
|
6876
|
-
compose as
|
|
6877
|
-
scale as
|
|
6878
|
-
translate as
|
|
7882
|
+
applyToPoint as applyToPoint59,
|
|
7883
|
+
compose as compose14,
|
|
7884
|
+
scale as scale9,
|
|
7885
|
+
translate as translate14
|
|
6879
7886
|
} from "transformation-matrix";
|
|
6880
7887
|
|
|
6881
7888
|
// lib/pcb/svg-object-fns/convert-circuit-json-to-solder-paste-mask.ts
|
|
6882
|
-
import { applyToPoint as
|
|
7889
|
+
import { applyToPoint as applyToPoint58 } from "transformation-matrix";
|
|
6883
7890
|
function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
|
|
6884
7891
|
const { transform, layer: layerFilter } = ctx;
|
|
6885
7892
|
if (layerFilter && solderPaste.layer !== layerFilter) return [];
|
|
6886
|
-
const [x, y] =
|
|
7893
|
+
const [x, y] = applyToPoint58(transform, [solderPaste.x, solderPaste.y]);
|
|
6887
7894
|
if (solderPaste.shape === "rect" || solderPaste.shape === "rotated_rect") {
|
|
6888
7895
|
const width = solderPaste.width * Math.abs(transform.a);
|
|
6889
7896
|
const height = solderPaste.height * Math.abs(transform.d);
|
|
@@ -6958,7 +7965,7 @@ function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
|
|
|
6958
7965
|
}
|
|
6959
7966
|
|
|
6960
7967
|
// lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
|
|
6961
|
-
var
|
|
7968
|
+
var OBJECT_ORDER4 = [
|
|
6962
7969
|
"pcb_board",
|
|
6963
7970
|
"pcb_solder_paste"
|
|
6964
7971
|
];
|
|
@@ -6991,12 +7998,12 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
6991
7998
|
const scaleFactor = Math.min(scaleX, scaleY);
|
|
6992
7999
|
const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
|
|
6993
8000
|
const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
|
|
6994
|
-
const transform =
|
|
6995
|
-
|
|
8001
|
+
const transform = compose14(
|
|
8002
|
+
translate14(
|
|
6996
8003
|
offsetX - minX * scaleFactor + padding * scaleFactor,
|
|
6997
8004
|
svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
|
|
6998
8005
|
),
|
|
6999
|
-
|
|
8006
|
+
scale9(scaleFactor, -scaleFactor)
|
|
7000
8007
|
// Flip in y-direction
|
|
7001
8008
|
);
|
|
7002
8009
|
const ctx = {
|
|
@@ -7005,8 +8012,8 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
7005
8012
|
colorMap: DEFAULT_PCB_COLOR_MAP
|
|
7006
8013
|
};
|
|
7007
8014
|
const svgObjects = filteredCircuitJson.sort(
|
|
7008
|
-
(a, b) => (
|
|
7009
|
-
).flatMap((item) =>
|
|
8015
|
+
(a, b) => (OBJECT_ORDER4.indexOf(b.type) ?? 9999) - (OBJECT_ORDER4.indexOf(a.type) ?? 9999)
|
|
8016
|
+
).flatMap((item) => createSvgObjects4({ elm: item, ctx }));
|
|
7010
8017
|
const softwareUsedString = getSoftwareUsedString(circuitJson);
|
|
7011
8018
|
const version = CIRCUIT_TO_SVG_VERSION;
|
|
7012
8019
|
const svgObject = {
|
|
@@ -7052,7 +8059,7 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
7052
8059
|
].filter((child) => child !== null)
|
|
7053
8060
|
};
|
|
7054
8061
|
try {
|
|
7055
|
-
return
|
|
8062
|
+
return stringify5(svgObject);
|
|
7056
8063
|
} catch (error) {
|
|
7057
8064
|
console.error("Error stringifying SVG object:", error);
|
|
7058
8065
|
throw error;
|
|
@@ -7074,7 +8081,7 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
7074
8081
|
}
|
|
7075
8082
|
}
|
|
7076
8083
|
}
|
|
7077
|
-
function
|
|
8084
|
+
function createSvgObjects4({ elm, ctx }) {
|
|
7078
8085
|
const { transform } = ctx;
|
|
7079
8086
|
switch (elm.type) {
|
|
7080
8087
|
case "pcb_board":
|
|
@@ -7086,8 +8093,8 @@ function createSvgObjects3({ elm, ctx }) {
|
|
|
7086
8093
|
}
|
|
7087
8094
|
}
|
|
7088
8095
|
function createSvgObjectFromPcbBoundary2(transform, minX, minY, maxX, maxY) {
|
|
7089
|
-
const [x1, y1] =
|
|
7090
|
-
const [x2, y2] =
|
|
8096
|
+
const [x1, y1] = applyToPoint59(transform, [minX, minY]);
|
|
8097
|
+
const [x2, y2] = applyToPoint59(transform, [maxX, maxY]);
|
|
7091
8098
|
const width = Math.abs(x2 - x1);
|
|
7092
8099
|
const height = Math.abs(y2 - y1);
|
|
7093
8100
|
const x = Math.min(x1, x2);
|
|
@@ -7115,6 +8122,7 @@ export {
|
|
|
7115
8122
|
circuitJsonToSchematicSvg,
|
|
7116
8123
|
convertCircuitJsonToAssemblySvg,
|
|
7117
8124
|
convertCircuitJsonToPcbSvg,
|
|
8125
|
+
convertCircuitJsonToPinoutSvg,
|
|
7118
8126
|
convertCircuitJsonToSchematicSvg,
|
|
7119
8127
|
convertCircuitJsonToSolderPasteMask,
|
|
7120
8128
|
createSvgObjectsForSchComponentPortHovers,
|