altium-toolkit 1.1.35 → 1.1.37
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/AGENTS.md +17 -2
- package/package.json +1 -1
- package/src/core/altium/PrintableTextDecoder.mjs +20 -1
- package/src/core/altium/SchematicMultipartOwnerMatcher.mjs +288 -7
- package/src/core/altium/SchematicTextParser.mjs +18 -253
- package/src/core/altium/SchematicTitleBlockParser.mjs +410 -0
- package/src/core/altium/SelectedPartAltiumExportAdapter.mjs +215 -0
- package/src/parser.mjs +1 -0
- package/src/ui/AltiumScene3dAuthoredBodyAnchorAdapter.mjs +245 -12
- package/src/ui/AltiumScene3dAuthoredConnectorYawPolicy.mjs +176 -0
- package/src/ui/AltiumScene3dBottomSourceHalfTurnPolicy.mjs +93 -0
- package/src/ui/AltiumScene3dDisplayModuleYawPolicy.mjs +284 -0
- package/src/ui/AltiumScene3dExternalPlacementAdapter.mjs +521 -23
- package/src/ui/AltiumScene3dPlacementRotationPolicy.mjs +766 -19
- package/src/ui/AltiumScene3dQfnFootprintDetector.mjs +307 -0
- package/src/ui/AltiumScene3dRepeatedFullFootprintBodyCollapse.mjs +518 -0
- package/src/ui/AltiumScene3dRepeatedModelOwnerRepair.mjs +121 -17
- package/src/ui/AltiumScene3dShapeStackOwnerAdapter.mjs +286 -135
- package/src/ui/AltiumScene3dShapeStackOwnerConflictPolicy.mjs +299 -0
- package/src/ui/PcbScene3dBoardOutlineRefiner.mjs +22 -0
- package/src/ui/PcbScene3dBuilder.mjs +613 -117
- package/src/ui/PcbScene3dModelRegistry.mjs +222 -10
- package/src/ui/PcbScene3dPackages.mjs +16 -1
- package/src/ui/PcbScene3dPlacementSideResolver.mjs +262 -22
- package/src/ui/PcbScene3dStaticBodyOwnerPromotion.mjs +984 -0
- package/src/ui/PcbScene3dStaticBodyPadOwnerPromotion.mjs +378 -0
- package/src/ui/PcbScene3dStaticBodyPlacementBuilder.mjs +169 -23
- package/src/ui/PcbScene3dStaticBodyPrototypeRecovery.mjs +445 -0
- package/src/ui/PcbScene3dStaticBodyRecovery.mjs +7 -1
- package/src/ui/PcbScene3dStaticBodySelectionKeyBuilder.mjs +199 -2
- package/src/ui/PcbScene3dStaticBodySymmetricOwnerPromotion.mjs +439 -0
- package/src/ui/PcbScene3dStaticBodySymmetryRecovery.mjs +23 -2
- package/src/ui/SchematicColorResolver.mjs +44 -0
- package/src/ui/SchematicLineColorResolver.mjs +1 -1
- package/src/ui/SchematicShapeRenderer.mjs +13 -13
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
/(?:^|[^a-z0-9])(?:clock|crystal|osc|oscillator|resonator|tcxo|txco|xtal)(?:$|[^a-z0-9])/i
|
|
3
|
-
const TIMING_DESIGNATOR_PATTERN = /^(?:y|xo)\d+[a-z]?$/i
|
|
1
|
+
import { AltiumScene3dShapeStackOwnerConflictPolicy } from './AltiumScene3dShapeStackOwnerConflictPolicy.mjs'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Keeps authored shape-based sub-bodies grouped under their carrier owner.
|
|
@@ -10,7 +8,8 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
10
8
|
static #EXACT_OWNER_TOLERANCE_MIL = 1
|
|
11
9
|
static #STACK_BODY_RADIUS_MIL = 220
|
|
12
10
|
static #HEIGHT_TOLERANCE_MIL = 0.1
|
|
13
|
-
|
|
11
|
+
static #OPPOSITE_SIDE_OWNER_DISTANCE_MARGIN_MIL = 10
|
|
12
|
+
static #STACK_BODY_OWNER_CONFLICT_MARGIN_MIL = 5
|
|
14
13
|
/**
|
|
15
14
|
* Applies authored stack ownership to static and external placements.
|
|
16
15
|
* @param {object} sceneDescription Built scene description.
|
|
@@ -53,23 +52,25 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
53
52
|
])
|
|
54
53
|
)
|
|
55
54
|
|
|
55
|
+
const repairedExternalPlacements =
|
|
56
|
+
AltiumScene3dShapeStackOwnerAdapter.#repairExternalPlacements(
|
|
57
|
+
sceneDescription.externalPlacements,
|
|
58
|
+
componentBodies,
|
|
59
|
+
assignments,
|
|
60
|
+
sceneDescription.board,
|
|
61
|
+
components
|
|
62
|
+
)
|
|
63
|
+
|
|
56
64
|
return {
|
|
57
65
|
...sceneDescription,
|
|
58
66
|
components: AltiumScene3dShapeStackOwnerAdapter.#markComponents(
|
|
59
67
|
sceneDescription.components,
|
|
60
68
|
ownerGroupKeys
|
|
61
69
|
),
|
|
62
|
-
externalPlacements:
|
|
63
|
-
AltiumScene3dShapeStackOwnerAdapter.#repairExternalPlacements(
|
|
64
|
-
sceneDescription.externalPlacements,
|
|
65
|
-
componentBodies,
|
|
66
|
-
assignments,
|
|
67
|
-
sceneDescription.board
|
|
68
|
-
),
|
|
70
|
+
externalPlacements: repairedExternalPlacements,
|
|
69
71
|
staticBodyPlacements:
|
|
70
72
|
AltiumScene3dShapeStackOwnerAdapter.#repairStaticPlacements(
|
|
71
73
|
sceneDescription.staticBodyPlacements,
|
|
72
|
-
componentBodies,
|
|
73
74
|
assignments,
|
|
74
75
|
sceneDescription.board
|
|
75
76
|
)
|
|
@@ -102,17 +103,19 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
102
103
|
* @param {object[]} componentBodies Source component-body rows.
|
|
103
104
|
* @param {object[]} assignments Carrier assignments.
|
|
104
105
|
* @param {object | undefined} board Scene board metadata.
|
|
106
|
+
* @param {object[]} components Source components.
|
|
105
107
|
* @returns {object[]}
|
|
106
108
|
*/
|
|
107
109
|
static #repairExternalPlacements(
|
|
108
110
|
placements,
|
|
109
111
|
componentBodies,
|
|
110
112
|
assignments,
|
|
111
|
-
board
|
|
113
|
+
board,
|
|
114
|
+
components
|
|
112
115
|
) {
|
|
113
116
|
const usedComponentBodies = new Set()
|
|
114
117
|
|
|
115
|
-
return (Array.isArray(placements) ? placements : []).
|
|
118
|
+
return (Array.isArray(placements) ? placements : []).flatMap(
|
|
116
119
|
(placement) => {
|
|
117
120
|
const componentBody =
|
|
118
121
|
AltiumScene3dShapeStackOwnerAdapter.#resolveComponentBody(
|
|
@@ -127,18 +130,27 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
127
130
|
const assignment =
|
|
128
131
|
AltiumScene3dShapeStackOwnerAdapter.#assignmentForBody(
|
|
129
132
|
componentBody,
|
|
130
|
-
assignments
|
|
133
|
+
assignments,
|
|
134
|
+
components
|
|
131
135
|
)
|
|
132
136
|
if (!assignment) {
|
|
133
|
-
return
|
|
137
|
+
return AltiumScene3dShapeStackOwnerAdapter.#shouldDropConflictingStackBody(
|
|
138
|
+
componentBody,
|
|
139
|
+
assignments,
|
|
140
|
+
components
|
|
141
|
+
)
|
|
142
|
+
? []
|
|
143
|
+
: [placement]
|
|
134
144
|
}
|
|
135
145
|
|
|
136
|
-
return
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
return [
|
|
147
|
+
AltiumScene3dShapeStackOwnerAdapter.#withOwner(
|
|
148
|
+
placement,
|
|
149
|
+
componentBody,
|
|
150
|
+
assignment,
|
|
151
|
+
board
|
|
152
|
+
)
|
|
153
|
+
]
|
|
142
154
|
}
|
|
143
155
|
)
|
|
144
156
|
}
|
|
@@ -146,17 +158,11 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
146
158
|
/**
|
|
147
159
|
* Repairs carrier static body ownership.
|
|
148
160
|
* @param {object[] | undefined} placements Scene static body placements.
|
|
149
|
-
* @param {object[]} componentBodies Source component-body rows.
|
|
150
161
|
* @param {object[]} assignments Carrier assignments.
|
|
151
162
|
* @param {object | undefined} board Scene board metadata.
|
|
152
163
|
* @returns {object[]}
|
|
153
164
|
*/
|
|
154
|
-
static #repairStaticPlacements(
|
|
155
|
-
placements,
|
|
156
|
-
componentBodies,
|
|
157
|
-
assignments,
|
|
158
|
-
board
|
|
159
|
-
) {
|
|
165
|
+
static #repairStaticPlacements(placements, assignments, board) {
|
|
160
166
|
return (Array.isArray(placements) ? placements : []).map(
|
|
161
167
|
(placement) => {
|
|
162
168
|
const assignment = assignments.find((candidate) =>
|
|
@@ -169,21 +175,103 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
169
175
|
return placement
|
|
170
176
|
}
|
|
171
177
|
|
|
172
|
-
return
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
placement?.positionMil,
|
|
178
|
-
assignment.owner,
|
|
179
|
-
board
|
|
180
|
-
),
|
|
181
|
-
coLocatedVariantGroupKey: assignment.groupKey
|
|
182
|
-
}
|
|
178
|
+
return AltiumScene3dShapeStackOwnerAdapter.#withStaticOwner(
|
|
179
|
+
placement,
|
|
180
|
+
assignment,
|
|
181
|
+
board
|
|
182
|
+
)
|
|
183
183
|
}
|
|
184
184
|
)
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Applies one stack owner to a repaired static carrier body.
|
|
189
|
+
* @param {object} placement Static body placement.
|
|
190
|
+
* @param {{ owner: object, groupKey: string }} assignment Stack assignment.
|
|
191
|
+
* @param {object | undefined} board Scene board metadata.
|
|
192
|
+
* @returns {object}
|
|
193
|
+
*/
|
|
194
|
+
static #withStaticOwner(placement, assignment, board) {
|
|
195
|
+
const ownerDesignator = String(assignment?.owner?.designator || '')
|
|
196
|
+
const mountSide =
|
|
197
|
+
AltiumScene3dShapeStackOwnerAdapter.#mountSide(assignment?.owner) ||
|
|
198
|
+
placement?.mountSide
|
|
199
|
+
const sidePlacement =
|
|
200
|
+
AltiumScene3dShapeStackOwnerAdapter.#withStaticMountSide(
|
|
201
|
+
placement,
|
|
202
|
+
mountSide
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
...sidePlacement,
|
|
207
|
+
designator: ownerDesignator,
|
|
208
|
+
selectionKey: ownerDesignator || sidePlacement.selectionKey,
|
|
209
|
+
positionMil: AltiumScene3dShapeStackOwnerAdapter.#withOwnerAnchor(
|
|
210
|
+
sidePlacement?.positionMil,
|
|
211
|
+
assignment.owner,
|
|
212
|
+
board
|
|
213
|
+
),
|
|
214
|
+
coLocatedVariantGroupKey: assignment.groupKey
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Applies a static placement side while preserving its height magnitude.
|
|
220
|
+
* @param {object} placement Static body placement.
|
|
221
|
+
* @param {string | undefined} mountSide Owner mount side.
|
|
222
|
+
* @returns {object}
|
|
223
|
+
*/
|
|
224
|
+
static #withStaticMountSide(placement, mountSide) {
|
|
225
|
+
const currentSide =
|
|
226
|
+
AltiumScene3dShapeStackOwnerAdapter.#normalizeMountSide(
|
|
227
|
+
placement?.mountSide
|
|
228
|
+
)
|
|
229
|
+
const side = AltiumScene3dShapeStackOwnerAdapter.#normalizeMountSide(
|
|
230
|
+
mountSide || currentSide
|
|
231
|
+
)
|
|
232
|
+
const z = Math.abs(Number(placement?.positionMil?.z || 0))
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
...placement,
|
|
236
|
+
mountSide: side,
|
|
237
|
+
positionMil: {
|
|
238
|
+
...(placement?.positionMil || {}),
|
|
239
|
+
z: side === 'bottom' ? -z : z
|
|
240
|
+
},
|
|
241
|
+
geometry:
|
|
242
|
+
currentSide === side
|
|
243
|
+
? placement?.geometry
|
|
244
|
+
: AltiumScene3dShapeStackOwnerAdapter.#mirrorStaticGeometry(
|
|
245
|
+
placement
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Mirrors source-coordinate static geometry for the opposite board side.
|
|
252
|
+
* @param {{ sourceCoordinateFrame?: boolean, geometry?: object }} placement Static body placement.
|
|
253
|
+
* @returns {object | undefined}
|
|
254
|
+
*/
|
|
255
|
+
static #mirrorStaticGeometry(placement) {
|
|
256
|
+
const geometry = placement?.geometry
|
|
257
|
+
if (
|
|
258
|
+
!placement?.sourceCoordinateFrame ||
|
|
259
|
+
!Array.isArray(geometry?.verticesMil)
|
|
260
|
+
) {
|
|
261
|
+
return geometry
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
...geometry,
|
|
266
|
+
verticesMil: geometry.verticesMil.map((vertex) => ({
|
|
267
|
+
x: AltiumScene3dShapeStackOwnerAdapter.#round(vertex?.x || 0),
|
|
268
|
+
y: AltiumScene3dShapeStackOwnerAdapter.#round(
|
|
269
|
+
-Number(vertex?.y || 0)
|
|
270
|
+
)
|
|
271
|
+
}))
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
187
275
|
/**
|
|
188
276
|
* Re-anchors a repaired static carrier on the owning component position.
|
|
189
277
|
* @param {object | undefined} position Existing render position.
|
|
@@ -214,7 +302,9 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
214
302
|
AltiumScene3dShapeStackOwnerAdapter.#isCarrierBase(body)
|
|
215
303
|
)
|
|
216
304
|
const timingComponents = components.filter((component) =>
|
|
217
|
-
|
|
305
|
+
AltiumScene3dShapeStackOwnerConflictPolicy.isTimingComponent(
|
|
306
|
+
component
|
|
307
|
+
)
|
|
218
308
|
)
|
|
219
309
|
const groups =
|
|
220
310
|
AltiumScene3dShapeStackOwnerAdapter.#groupCarrierBases(bases)
|
|
@@ -229,20 +319,26 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
229
319
|
return []
|
|
230
320
|
}
|
|
231
321
|
|
|
232
|
-
const owners =
|
|
233
|
-
.
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
322
|
+
const owners =
|
|
323
|
+
AltiumScene3dShapeStackOwnerConflictPolicy.preferredSideOwners(
|
|
324
|
+
group.anchor,
|
|
325
|
+
timingComponents.filter(
|
|
326
|
+
(component) =>
|
|
327
|
+
AltiumScene3dShapeStackOwnerAdapter.#distance(
|
|
328
|
+
group.anchor,
|
|
329
|
+
component
|
|
330
|
+
) <=
|
|
331
|
+
AltiumScene3dShapeStackOwnerAdapter
|
|
332
|
+
.#BASE_OWNER_TOLERANCE_MIL
|
|
333
|
+
),
|
|
334
|
+
AltiumScene3dShapeStackOwnerAdapter
|
|
335
|
+
.#OPPOSITE_SIDE_OWNER_DISTANCE_MARGIN_MIL
|
|
336
|
+
).sort(
|
|
243
337
|
(left, right) =>
|
|
244
|
-
|
|
245
|
-
|
|
338
|
+
AltiumScene3dShapeStackOwnerConflictPolicy.ownerRank(
|
|
339
|
+
right
|
|
340
|
+
) -
|
|
341
|
+
AltiumScene3dShapeStackOwnerConflictPolicy.ownerRank(
|
|
246
342
|
left
|
|
247
343
|
) ||
|
|
248
344
|
String(left?.designator || '').localeCompare(
|
|
@@ -305,12 +401,12 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
305
401
|
return (
|
|
306
402
|
exactOwners.some(
|
|
307
403
|
(component) =>
|
|
308
|
-
!
|
|
404
|
+
!AltiumScene3dShapeStackOwnerConflictPolicy.isTimingComponent(
|
|
309
405
|
component
|
|
310
406
|
)
|
|
311
407
|
) &&
|
|
312
408
|
!exactOwners.some((component) =>
|
|
313
|
-
|
|
409
|
+
AltiumScene3dShapeStackOwnerConflictPolicy.isTimingComponent(
|
|
314
410
|
component
|
|
315
411
|
)
|
|
316
412
|
)
|
|
@@ -368,9 +464,109 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
368
464
|
* Finds a carrier assignment for one positive-height sub-body.
|
|
369
465
|
* @param {object | null} componentBody Source component-body row.
|
|
370
466
|
* @param {object[]} assignments Carrier assignments.
|
|
467
|
+
* @param {object[]} components Source components.
|
|
371
468
|
* @returns {object | null}
|
|
372
469
|
*/
|
|
373
|
-
static #assignmentForBody(componentBody, assignments) {
|
|
470
|
+
static #assignmentForBody(componentBody, assignments, components) {
|
|
471
|
+
return (
|
|
472
|
+
AltiumScene3dShapeStackOwnerAdapter.#assignmentCandidatesForBody(
|
|
473
|
+
componentBody,
|
|
474
|
+
assignments
|
|
475
|
+
)
|
|
476
|
+
.filter((candidate) =>
|
|
477
|
+
AltiumScene3dShapeStackOwnerAdapter.#canAssignStackBodyCandidate(
|
|
478
|
+
componentBody,
|
|
479
|
+
candidate,
|
|
480
|
+
components
|
|
481
|
+
)
|
|
482
|
+
)
|
|
483
|
+
.sort(
|
|
484
|
+
(left, right) =>
|
|
485
|
+
left.heightError - right.heightError ||
|
|
486
|
+
left.distance - right.distance
|
|
487
|
+
)[0]?.assignment || null
|
|
488
|
+
)
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Checks whether a candidate stack owner can claim a raised body.
|
|
493
|
+
* @param {object | null} componentBody Source component-body row.
|
|
494
|
+
* @param {{ assignment: { owner: object } }} candidate Candidate assignment row.
|
|
495
|
+
* @param {object[]} components Source components.
|
|
496
|
+
* @returns {boolean}
|
|
497
|
+
*/
|
|
498
|
+
static #canAssignStackBodyCandidate(componentBody, candidate, components) {
|
|
499
|
+
const hasConflictingOwner =
|
|
500
|
+
AltiumScene3dShapeStackOwnerConflictPolicy.hasConflictingComponentOwner(
|
|
501
|
+
componentBody,
|
|
502
|
+
candidate.assignment.owner,
|
|
503
|
+
components,
|
|
504
|
+
AltiumScene3dShapeStackOwnerAdapter
|
|
505
|
+
.#STACK_BODY_OWNER_CONFLICT_MARGIN_MIL
|
|
506
|
+
)
|
|
507
|
+
if (!hasConflictingOwner) {
|
|
508
|
+
return true
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return (
|
|
512
|
+
AltiumScene3dShapeStackOwnerConflictPolicy.hasStackDetailBodyIdentity(
|
|
513
|
+
componentBody
|
|
514
|
+
) &&
|
|
515
|
+
!AltiumScene3dShapeStackOwnerConflictPolicy.hasExactOppositeSideOwner(
|
|
516
|
+
componentBody,
|
|
517
|
+
candidate.assignment.owner,
|
|
518
|
+
components,
|
|
519
|
+
AltiumScene3dShapeStackOwnerAdapter.#EXACT_OWNER_TOLERANCE_MIL
|
|
520
|
+
)
|
|
521
|
+
)
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Checks whether an unassigned positive-height body should be suppressed
|
|
526
|
+
* because it conflicts with an opposite-side owner but has no exact owner
|
|
527
|
+
* of its own.
|
|
528
|
+
* @param {object | null} componentBody Source component-body row.
|
|
529
|
+
* @param {object[]} assignments Carrier assignments.
|
|
530
|
+
* @param {object[]} components Source components.
|
|
531
|
+
* @returns {boolean}
|
|
532
|
+
*/
|
|
533
|
+
static #shouldDropConflictingStackBody(
|
|
534
|
+
componentBody,
|
|
535
|
+
assignments,
|
|
536
|
+
components
|
|
537
|
+
) {
|
|
538
|
+
const conflict =
|
|
539
|
+
AltiumScene3dShapeStackOwnerAdapter.#assignmentCandidatesForBody(
|
|
540
|
+
componentBody,
|
|
541
|
+
assignments
|
|
542
|
+
).find((candidate) =>
|
|
543
|
+
AltiumScene3dShapeStackOwnerConflictPolicy.hasConflictingComponentOwner(
|
|
544
|
+
componentBody,
|
|
545
|
+
candidate.assignment.owner,
|
|
546
|
+
components,
|
|
547
|
+
AltiumScene3dShapeStackOwnerAdapter
|
|
548
|
+
.#STACK_BODY_OWNER_CONFLICT_MARGIN_MIL
|
|
549
|
+
)
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
return Boolean(
|
|
553
|
+
conflict &&
|
|
554
|
+
!AltiumScene3dShapeStackOwnerConflictPolicy.hasExactOppositeSideOwner(
|
|
555
|
+
componentBody,
|
|
556
|
+
conflict.assignment.owner,
|
|
557
|
+
components,
|
|
558
|
+
AltiumScene3dShapeStackOwnerAdapter.#EXACT_OWNER_TOLERANCE_MIL
|
|
559
|
+
)
|
|
560
|
+
)
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Builds stack assignment candidates for one positive-height body.
|
|
565
|
+
* @param {object | null} componentBody Source component-body row.
|
|
566
|
+
* @param {object[]} assignments Carrier assignments.
|
|
567
|
+
* @returns {{ assignment: object, heightError: number, distance: number }[]}
|
|
568
|
+
*/
|
|
569
|
+
static #assignmentCandidatesForBody(componentBody, assignments) {
|
|
374
570
|
if (
|
|
375
571
|
!componentBody ||
|
|
376
572
|
!AltiumScene3dShapeStackOwnerAdapter.#isShapeBasedBody(
|
|
@@ -378,7 +574,7 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
378
574
|
) ||
|
|
379
575
|
Number(componentBody?.standoffHeightMil || 0) <= 0
|
|
380
576
|
) {
|
|
381
|
-
return
|
|
577
|
+
return []
|
|
382
578
|
}
|
|
383
579
|
|
|
384
580
|
const standoff = Number(componentBody.standoffHeightMil)
|
|
@@ -386,33 +582,26 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
386
582
|
componentBody.positionMil
|
|
387
583
|
)
|
|
388
584
|
|
|
389
|
-
return (
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
assignment.owner
|
|
399
|
-
)
|
|
400
|
-
}))
|
|
401
|
-
.filter(
|
|
402
|
-
(candidate) =>
|
|
403
|
-
candidate.heightError <=
|
|
404
|
-
AltiumScene3dShapeStackOwnerAdapter
|
|
405
|
-
.#HEIGHT_TOLERANCE_MIL &&
|
|
406
|
-
candidate.distance <=
|
|
407
|
-
AltiumScene3dShapeStackOwnerAdapter
|
|
408
|
-
.#STACK_BODY_RADIUS_MIL
|
|
585
|
+
return (Array.isArray(assignments) ? assignments : [])
|
|
586
|
+
.map((assignment) => ({
|
|
587
|
+
assignment,
|
|
588
|
+
heightError: Math.abs(
|
|
589
|
+
Number(assignment.heightMil || 0) - standoff
|
|
590
|
+
),
|
|
591
|
+
distance: AltiumScene3dShapeStackOwnerAdapter.#distance(
|
|
592
|
+
bodyPosition,
|
|
593
|
+
assignment.owner
|
|
409
594
|
)
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
595
|
+
}))
|
|
596
|
+
.filter(
|
|
597
|
+
(candidate) =>
|
|
598
|
+
candidate.heightError <=
|
|
599
|
+
AltiumScene3dShapeStackOwnerAdapter
|
|
600
|
+
.#HEIGHT_TOLERANCE_MIL &&
|
|
601
|
+
candidate.distance <=
|
|
602
|
+
AltiumScene3dShapeStackOwnerAdapter
|
|
603
|
+
.#STACK_BODY_RADIUS_MIL
|
|
604
|
+
)
|
|
416
605
|
}
|
|
417
606
|
|
|
418
607
|
/**
|
|
@@ -619,57 +808,6 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
619
808
|
: 0
|
|
620
809
|
}
|
|
621
810
|
|
|
622
|
-
/**
|
|
623
|
-
* Checks whether a component is a timing-package owner.
|
|
624
|
-
* @param {object} component Source component.
|
|
625
|
-
* @returns {boolean}
|
|
626
|
-
*/
|
|
627
|
-
static #isTimingComponent(component) {
|
|
628
|
-
const designator = String(component?.designator || '').trim()
|
|
629
|
-
|
|
630
|
-
return (
|
|
631
|
-
TIMING_DESIGNATOR_PATTERN.test(designator) ||
|
|
632
|
-
TIMING_PACKAGE_PATTERN.test(
|
|
633
|
-
[
|
|
634
|
-
component?.pattern,
|
|
635
|
-
component?.source,
|
|
636
|
-
component?.description,
|
|
637
|
-
component?.provenance?.footprintDescription,
|
|
638
|
-
...Object.values(component?.parameters || {})
|
|
639
|
-
]
|
|
640
|
-
.map((value) => String(value || ''))
|
|
641
|
-
.join(' ')
|
|
642
|
-
)
|
|
643
|
-
)
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* Scores how strongly a component looks like the fitted stack owner.
|
|
648
|
-
* @param {object} component Source component.
|
|
649
|
-
* @returns {number}
|
|
650
|
-
*/
|
|
651
|
-
static #ownerRank(component) {
|
|
652
|
-
const parameters = Object.values(component?.parameters || {}).filter(
|
|
653
|
-
(value) => String(value || '').trim()
|
|
654
|
-
)
|
|
655
|
-
return (
|
|
656
|
-
parameters.length * 10 +
|
|
657
|
-
(TIMING_DESIGNATOR_PATTERN.test(component?.designator) ? 5 : 0) +
|
|
658
|
-
(TIMING_PACKAGE_PATTERN.test(
|
|
659
|
-
[
|
|
660
|
-
component?.pattern,
|
|
661
|
-
component?.source,
|
|
662
|
-
component?.description,
|
|
663
|
-
component?.provenance?.footprintDescription
|
|
664
|
-
]
|
|
665
|
-
.map((value) => String(value || ''))
|
|
666
|
-
.join(' ')
|
|
667
|
-
)
|
|
668
|
-
? 3
|
|
669
|
-
: 0)
|
|
670
|
-
)
|
|
671
|
-
}
|
|
672
|
-
|
|
673
811
|
/**
|
|
674
812
|
* Checks whether one body row came from shape-based component metadata.
|
|
675
813
|
* @param {object | null | undefined} componentBody Source body row.
|
|
@@ -691,6 +829,19 @@ export class AltiumScene3dShapeStackOwnerAdapter {
|
|
|
691
829
|
return layer.includes('BOTTOM') || layer === 'BOT' ? 'bottom' : 'top'
|
|
692
830
|
}
|
|
693
831
|
|
|
832
|
+
/**
|
|
833
|
+
* Normalizes a static placement side token.
|
|
834
|
+
* @param {string | undefined} mountSide Candidate mount side.
|
|
835
|
+
* @returns {'top' | 'bottom'}
|
|
836
|
+
*/
|
|
837
|
+
static #normalizeMountSide(mountSide) {
|
|
838
|
+
return String(mountSide || 'top')
|
|
839
|
+
.trim()
|
|
840
|
+
.toLowerCase() === 'bottom'
|
|
841
|
+
? 'bottom'
|
|
842
|
+
: 'top'
|
|
843
|
+
}
|
|
844
|
+
|
|
694
845
|
/**
|
|
695
846
|
* Resolves one board face Z coordinate.
|
|
696
847
|
* @param {string} mountSide Mount side.
|