altium-toolkit 1.4.2 → 1.4.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.
@@ -0,0 +1,20 @@
1
+ # altium-toolkit 1.4.3
2
+
3
+ Version 1.4.3 keeps PCB fabrication details on their authored board side when
4
+ preparing side-resolved render models.
5
+
6
+ ## Side-correct PCB fabrication details
7
+
8
+ - Front-side views retain top overlay, paste, and solder-mask primitives while
9
+ excluding their bottom-side counterparts.
10
+ - Back-side views retain bottom overlay, paste, and solder-mask primitives while
11
+ excluding their top-side counterparts.
12
+ - Shared mechanical and documentation layers remain visible on both sides.
13
+ - Copper projection continues to use the established native Altium behavior.
14
+
15
+ ## Verification
16
+
17
+ - A side-resolution regression covers fills, tracks, arcs, regions,
18
+ shape-based regions, and board regions with neutral-layer preservation.
19
+ - The complete package suite, formatting, and npm dry-run gates verify the
20
+ release.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "altium-toolkit",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "Altium document parsing and non-interactive rendering utilities",
5
5
  "keywords": [
6
6
  "altium",
@@ -0,0 +1,132 @@
1
+ // SPDX-FileCopyrightText: 2026 André Fiedler
2
+ //
3
+ // SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ import { PcbLayerGroups } from '../core/altium/PcbLayerGroups.mjs'
6
+ import { PcbSideResolvedRenderModel as HistoricalPcbSideResolvedRenderModel } from '../ui/PcbSideResolvedRenderModel.mjs'
7
+
8
+ /**
9
+ * Adds side-correct fabrication detail filtering around the preserved native
10
+ * Altium side projection.
11
+ */
12
+ export class PcbSideResolvedRenderModel {
13
+ /**
14
+ * Resolves a normalized PCB model for the requested board side.
15
+ * @param {object | null} board
16
+ * @param {'front' | 'back' | { side?: 'front' | 'back' }} [options]
17
+ * @returns {object | null}
18
+ */
19
+ static resolve(board, options = {}) {
20
+ const side = PcbSideResolvedRenderModel.#normalizeSide(options)
21
+ const resolved = HistoricalPcbSideResolvedRenderModel.resolve(
22
+ board,
23
+ options
24
+ )
25
+ if (!resolved?.pcb) return resolved
26
+
27
+ const pcb = resolved.pcb
28
+ return {
29
+ ...resolved,
30
+ pcb: {
31
+ ...pcb,
32
+ fills: PcbSideResolvedRenderModel.#filterPrimitives(
33
+ pcb.fills,
34
+ side
35
+ ),
36
+ tracks: PcbSideResolvedRenderModel.#filterPrimitives(
37
+ pcb.tracks,
38
+ side
39
+ ),
40
+ arcs: PcbSideResolvedRenderModel.#filterPrimitives(
41
+ pcb.arcs,
42
+ side
43
+ ),
44
+ regions: PcbSideResolvedRenderModel.#filterPrimitives(
45
+ pcb.regions,
46
+ side
47
+ ),
48
+ shapeBasedRegions: PcbSideResolvedRenderModel.#filterPrimitives(
49
+ pcb.shapeBasedRegions,
50
+ side
51
+ ),
52
+ boardRegions: PcbSideResolvedRenderModel.#filterPrimitives(
53
+ pcb.boardRegions,
54
+ side
55
+ )
56
+ }
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Checks whether a primitive belongs to an Altium copper signal layer.
62
+ * @param {object | null} primitive
63
+ * @returns {boolean}
64
+ */
65
+ static isCopperPrimitive(primitive) {
66
+ return HistoricalPcbSideResolvedRenderModel.isCopperPrimitive(primitive)
67
+ }
68
+
69
+ /**
70
+ * Normalizes the caller side option.
71
+ * @param {'front' | 'back' | { side?: 'front' | 'back' }} options
72
+ * @returns {'front' | 'back'}
73
+ */
74
+ static #normalizeSide(options) {
75
+ if (options === 'back') return 'back'
76
+ if (options && typeof options === 'object' && options.side === 'back') {
77
+ return 'back'
78
+ }
79
+ return 'front'
80
+ }
81
+
82
+ /**
83
+ * Filters one primitive collection to the requested surface.
84
+ * @param {readonly object[] | undefined} primitives
85
+ * @param {'front' | 'back'} side
86
+ * @returns {object[]}
87
+ */
88
+ static #filterPrimitives(primitives, side) {
89
+ return (primitives || []).filter((primitive) =>
90
+ PcbSideResolvedRenderModel.#isPrimitiveVisibleOnSide(
91
+ primitive,
92
+ side
93
+ )
94
+ )
95
+ }
96
+
97
+ /**
98
+ * Checks whether a primitive belongs to the requested surface or a shared
99
+ * non-surface layer.
100
+ * @param {object | null} primitive
101
+ * @param {'front' | 'back'} side
102
+ * @returns {boolean}
103
+ */
104
+ static #isPrimitiveVisibleOnSide(primitive, side) {
105
+ const layerId = primitive?.layerId ?? primitive?.layerCode
106
+ if (PcbLayerGroups.isCopper(layerId)) return true
107
+
108
+ const layerSide = PcbLayerGroups.describeLayer(layerId).side
109
+ if (layerSide === 'top') return side === 'front'
110
+ if (layerSide === 'bottom') return side === 'back'
111
+ return true
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Resolves a normalized PCB model for the requested board side.
117
+ * @param {object | null} board
118
+ * @param {'front' | 'back' | { side?: 'front' | 'back' }} [options]
119
+ * @returns {object | null}
120
+ */
121
+ export function preparePcbSideResolvedRenderModel(board, options = {}) {
122
+ return PcbSideResolvedRenderModel.resolve(board, options)
123
+ }
124
+
125
+ /**
126
+ * Checks whether a primitive belongs to an Altium copper signal layer.
127
+ * @param {object | null} primitive
128
+ * @returns {boolean}
129
+ */
130
+ export function isCopperPrimitive(primitive) {
131
+ return PcbSideResolvedRenderModel.isCopperPrimitive(primitive)
132
+ }
@@ -15,7 +15,7 @@ export {
15
15
  PcbSideResolvedRenderModel,
16
16
  isCopperPrimitive,
17
17
  preparePcbSideResolvedRenderModel
18
- } from './ui/PcbSideResolvedRenderModel.mjs'
18
+ } from './convergence/PcbSideResolvedRenderModel.mjs'
19
19
  export { PcbSvgRenderer } from './ui/PcbSvgRenderer.mjs'
20
20
  export { SchematicColorResolver } from './ui/SchematicColorResolver.mjs'
21
21
  export { SchematicContentLayout } from './ui/SchematicContentLayout.mjs'