pcb-scene3d-viewer 1.3.2 → 1.3.3
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/README.md
CHANGED
|
@@ -42,6 +42,11 @@ short-circuits non-subdividing copper-fill clipping without changing its
|
|
|
42
42
|
observable geometry. See the
|
|
43
43
|
[1.3.2 release notes](docs/release-notes-v1.3.2.md).
|
|
44
44
|
|
|
45
|
+
Version 1.3.3 preserves validated STEP source anchors and avoids applying a
|
|
46
|
+
second quarter-turn when the imported assembly envelope proves that its depth
|
|
47
|
+
and height axes are already exchanged. See the
|
|
48
|
+
[1.3.3 release notes](docs/release-notes-v1.3.3.md).
|
|
49
|
+
|
|
45
50
|
## CircuitJSON 1.1 convergence
|
|
46
51
|
|
|
47
52
|
Version 1.2.2 accepts the common document and prepared-context shapes returned
|
|
@@ -150,6 +155,7 @@ const controller = new PcbScene3dController(viewportNode, document)
|
|
|
150
155
|
|
|
151
156
|
- [API](docs/api.md)
|
|
152
157
|
- [CircuitJSON usage](docs/circuitjson.md)
|
|
158
|
+
- [1.3.3 release notes](docs/release-notes-v1.3.3.md)
|
|
153
159
|
- [1.3.2 release notes](docs/release-notes-v1.3.2.md)
|
|
154
160
|
- [1.3.1 release notes](docs/release-notes-v1.3.1.md)
|
|
155
161
|
- [1.2.2 release notes](docs/release-notes-v1.2.2.md)
|
package/docs/model-format.md
CHANGED
|
@@ -186,6 +186,13 @@ Embedded STEP models can use:
|
|
|
186
186
|
}
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
+
For imported STEP assemblies, the runtime compares the fully assembled mesh
|
|
190
|
+
envelope with an authored model-bounds projection before applying a separate
|
|
191
|
+
quarter-turn around the model X axis. When the imported assembly has already
|
|
192
|
+
exchanged its depth and height axes, the duplicate tilt is omitted. Toolkits
|
|
193
|
+
can set `modelTransform.preserveSourceAnchor: true` when an authored body origin
|
|
194
|
+
must remain fixed without requesting component-center recovery.
|
|
195
|
+
|
|
189
196
|
## Detail Primitives
|
|
190
197
|
|
|
191
198
|
The runtime expects pre-normalized primitive lists for:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# pcb-scene3d-viewer 1.3.3
|
|
2
|
+
|
|
3
|
+
Version 1.3.3 improves external STEP placement when source-authored anchors and
|
|
4
|
+
pre-oriented assemblies are present.
|
|
5
|
+
|
|
6
|
+
## STEP placement fidelity
|
|
7
|
+
|
|
8
|
+
- An explicit `preserveSourceAnchor` transform keeps a validated source body
|
|
9
|
+
origin fixed without activating component-center recovery.
|
|
10
|
+
- Embedded STEP assemblies omit a duplicate quarter-turn only when their loaded
|
|
11
|
+
mesh envelope proves that the authored depth and height axes are already
|
|
12
|
+
exchanged.
|
|
13
|
+
- Board-space component yaw and the original external-model asset remain
|
|
14
|
+
unchanged.
|
|
15
|
+
|
|
16
|
+
## Compatibility
|
|
17
|
+
|
|
18
|
+
- Detection uses source origin, projection metadata, mesh dimensions, and
|
|
19
|
+
bounded error thresholds; it does not inspect filenames, project identities,
|
|
20
|
+
component labels, or library names.
|
|
21
|
+
- Existing scene colors, board geometry, and public APIs remain unchanged.
|
|
22
|
+
|
|
23
|
+
## Verification
|
|
24
|
+
|
|
25
|
+
- Repository-owned tests cover preserved source anchors and embedded-axis
|
|
26
|
+
normalization alongside the existing external-model placement suite.
|
|
27
|
+
- The complete package suite, formatting check, and npm package dry run are
|
|
28
|
+
required for release.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pcb-scene3d-viewer",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "Reusable Three.js PCB 3D scene viewer for normalized ECAD and CircuitJSON scene descriptions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pcb",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"docs/release-notes-v1.3.0.md",
|
|
40
40
|
"docs/release-notes-v1.3.1.md",
|
|
41
41
|
"docs/release-notes-v1.3.2.md",
|
|
42
|
+
"docs/release-notes-v1.3.3.md",
|
|
42
43
|
"docs/model-format.md",
|
|
43
44
|
"docs/testing.md",
|
|
44
45
|
"spec",
|
|
@@ -6,12 +6,13 @@ export class PcbScene3dExternalModelSourceOriginPolicy {
|
|
|
6
6
|
* Checks whether an explicit owner anchor should keep source-origin repair
|
|
7
7
|
* disabled. Translucent cover-sized bodies use corner-origin STEP data, so
|
|
8
8
|
* they still need the embedded source-origin correction.
|
|
9
|
-
* @param {{ bodyOpacity?: number | string, modelTransform?: { ownerAnchorOffsetMil?: object }, projection?: { boundsMil?: { width?: number, depth?: number } } }} placement Placement metadata.
|
|
9
|
+
* @param {{ bodyOpacity?: number | string, modelTransform?: { ownerAnchorOffsetMil?: object, preserveSourceAnchor?: boolean }, projection?: { boundsMil?: { width?: number, depth?: number } } }} placement Placement metadata.
|
|
10
10
|
* @returns {boolean}
|
|
11
11
|
*/
|
|
12
12
|
static shouldSkipOwnerAnchoredAdjustment(placement) {
|
|
13
13
|
return (
|
|
14
|
-
Boolean(placement?.modelTransform?.ownerAnchorOffsetMil)
|
|
14
|
+
(Boolean(placement?.modelTransform?.ownerAnchorOffsetMil) ||
|
|
15
|
+
placement?.modelTransform?.preserveSourceAnchor === true) &&
|
|
15
16
|
!PcbScene3dExternalModelSourceOriginPolicy.#isTransparentCoverSizedPlacement(
|
|
16
17
|
placement
|
|
17
18
|
)
|
|
@@ -362,7 +362,16 @@ export class PcbScene3dExternalModels {
|
|
|
362
362
|
viewCompensationGroup
|
|
363
363
|
)
|
|
364
364
|
const modelTransform = placement?.modelTransform || {}
|
|
365
|
-
const
|
|
365
|
+
const authoredModelRotation = modelTransform.rotationDeg || {}
|
|
366
|
+
const modelRotation =
|
|
367
|
+
PcbScene3dExternalModels.#resolveEmbeddedModelRotation(
|
|
368
|
+
placement,
|
|
369
|
+
modelGroup,
|
|
370
|
+
authoredModelRotation
|
|
371
|
+
)
|
|
372
|
+
if (modelRotation !== authoredModelRotation) {
|
|
373
|
+
modelGroup.userData.scene3dEmbeddedAxisTiltRepair = true
|
|
374
|
+
}
|
|
366
375
|
const modelOffset =
|
|
367
376
|
PcbScene3dExternalModels.#resolveModelOffset(modelTransform)
|
|
368
377
|
const sourceOriginAdjustment =
|
|
@@ -595,6 +604,73 @@ export class PcbScene3dExternalModels {
|
|
|
595
604
|
}
|
|
596
605
|
}
|
|
597
606
|
|
|
607
|
+
/**
|
|
608
|
+
* Removes a duplicated quarter-turn when the imported STEP assembly has
|
|
609
|
+
* already exchanged its authored depth and height axes. Native STEP point
|
|
610
|
+
* envelopes describe pre-assembly coordinates, while OCCT returns the
|
|
611
|
+
* fully placed mesh, so comparing both frames is required before applying
|
|
612
|
+
* the separate Altium body tilt.
|
|
613
|
+
* @param {{ externalModel?: { origin?: string }, projection?: { source?: string, boundsMil?: { depth?: number, height?: number } } }} placement Placement metadata.
|
|
614
|
+
* @param {{ userData?: { scene3dSourceBoundsMil?: { sizeY?: number, sizeZ?: number } } }} modelGroup Loaded model group.
|
|
615
|
+
* @param {{ x?: number, y?: number, z?: number }} modelRotation Authored model rotation.
|
|
616
|
+
* @returns {{ x?: number, y?: number, z?: number }}
|
|
617
|
+
*/
|
|
618
|
+
static #resolveEmbeddedModelRotation(placement, modelGroup, modelRotation) {
|
|
619
|
+
const sourceBounds = modelGroup?.userData?.scene3dSourceBoundsMil || {}
|
|
620
|
+
const projectionBounds = placement?.projection?.boundsMil || {}
|
|
621
|
+
const sourceY = Math.abs(Number(sourceBounds.sizeY || 0))
|
|
622
|
+
const sourceZ = Math.abs(Number(sourceBounds.sizeZ || 0))
|
|
623
|
+
const projectedDepth = Math.abs(Number(projectionBounds.depth || 0))
|
|
624
|
+
const projectedHeight = Math.abs(Number(projectionBounds.height || 0))
|
|
625
|
+
const tilt = PcbScene3dExternalModels.#normalizeAngle(modelRotation?.x)
|
|
626
|
+
const directError =
|
|
627
|
+
PcbScene3dExternalModels.#relativeDimensionError(
|
|
628
|
+
sourceY,
|
|
629
|
+
projectedDepth
|
|
630
|
+
) +
|
|
631
|
+
PcbScene3dExternalModels.#relativeDimensionError(
|
|
632
|
+
sourceZ,
|
|
633
|
+
projectedHeight
|
|
634
|
+
)
|
|
635
|
+
const exchangedError =
|
|
636
|
+
PcbScene3dExternalModels.#relativeDimensionError(
|
|
637
|
+
sourceY,
|
|
638
|
+
projectedHeight
|
|
639
|
+
) +
|
|
640
|
+
PcbScene3dExternalModels.#relativeDimensionError(
|
|
641
|
+
sourceZ,
|
|
642
|
+
projectedDepth
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
if (
|
|
646
|
+
String(placement?.externalModel?.origin || '').toLowerCase() !==
|
|
647
|
+
'embedded' ||
|
|
648
|
+
String(placement?.projection?.source || '').toLowerCase() !==
|
|
649
|
+
'model-bounds' ||
|
|
650
|
+
(tilt !== 90 && tilt !== 270) ||
|
|
651
|
+
Math.min(sourceY, sourceZ, projectedDepth, projectedHeight) <= 0 ||
|
|
652
|
+
Math.max(projectedDepth, projectedHeight) /
|
|
653
|
+
Math.min(projectedDepth, projectedHeight) <
|
|
654
|
+
1.25 ||
|
|
655
|
+
exchangedError > 0.2 ||
|
|
656
|
+
directError - exchangedError < 0.5
|
|
657
|
+
) {
|
|
658
|
+
return modelRotation
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
return { ...modelRotation, x: 0 }
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Measures a scale-independent dimension mismatch.
|
|
666
|
+
* @param {number} actual Imported dimension.
|
|
667
|
+
* @param {number} expected Authored dimension.
|
|
668
|
+
* @returns {number}
|
|
669
|
+
*/
|
|
670
|
+
static #relativeDimensionError(actual, expected) {
|
|
671
|
+
return Math.abs(actual - expected) / Math.max(actual, expected, 1)
|
|
672
|
+
}
|
|
673
|
+
|
|
598
674
|
/**
|
|
599
675
|
* Checks whether source Z is the model's intentional edge-extension axis
|
|
600
676
|
* instead of a square-package source-origin bias.
|