altium-toolkit 1.1.24 → 1.1.26

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.
Files changed (35) hide show
  1. package/README.md +5 -3
  2. package/docs/api.md +43 -17
  3. package/docs/model-format.md +51 -11
  4. package/docs/schemas/altium_toolkit/library_compatibility_a1.schema.json +116 -0
  5. package/docs/schemas/altium_toolkit/library_qa_a1.schema.json +3 -0
  6. package/docs/schemas/altium_toolkit/unsupported_features_a1.schema.json +58 -1
  7. package/package.json +1 -1
  8. package/spec/library-compatibility.md +65 -0
  9. package/src/core/altium/AltiumParser.mjs +8 -1
  10. package/src/core/altium/LibraryCompatibilityGeometry.mjs +618 -0
  11. package/src/core/altium/LibraryCompatibilityModelHintBuilder.mjs +296 -0
  12. package/src/core/altium/LibraryCompatibilityReportBuilder.mjs +930 -0
  13. package/src/core/altium/LibraryQaReportBuilder.mjs +29 -1
  14. package/src/core/altium/PcbDimensionParser.mjs +1 -0
  15. package/src/core/altium/PcbDimensionReportBuilder.mjs +190 -0
  16. package/src/core/altium/PcbEmbeddedModelExtractor.mjs +140 -10
  17. package/src/core/altium/PcbFabricationReadinessReportBuilder.mjs +607 -0
  18. package/src/core/altium/PcbInspectionReportBuilder.mjs +56 -3
  19. package/src/core/altium/PcbLayerStackReadModelBuilder.mjs +138 -3
  20. package/src/core/altium/PcbLibModelParser.mjs +24 -2
  21. package/src/core/altium/PcbLibStorageNameResolver.mjs +171 -0
  22. package/src/core/altium/PcbLibStreamExtractor.mjs +15 -93
  23. package/src/core/altium/PcbPrimitiveFieldOffsetReportBuilder.mjs +352 -0
  24. package/src/core/altium/PcbRuleImpactReportBuilder.mjs +313 -0
  25. package/src/core/altium/PcbShapeBasedBodyGeometryParser.mjs +514 -0
  26. package/src/core/altium/SchematicConnectivityQaBuilder.mjs +442 -2
  27. package/src/core/altium/SchematicImageDiagnosticsBuilder.mjs +214 -0
  28. package/src/core/altium/UnsupportedFeatureReportBuilder.mjs +523 -3
  29. package/src/parser.mjs +8 -0
  30. package/src/styles/altium-renderers.css +36 -0
  31. package/src/ui/PcbDimensionPrimitiveRenderer.mjs +422 -0
  32. package/src/ui/PcbScene3dBoardOutlineRefiner.mjs +6 -0
  33. package/src/ui/PcbScene3dBuilder.mjs +10 -2
  34. package/src/ui/PcbScene3dStaticBodyPlacementBuilder.mjs +225 -0
  35. package/src/ui/PcbSvgRenderer.mjs +78 -2
@@ -3,6 +3,7 @@
3
3
  // SPDX-License-Identifier: GPL-3.0-or-later
4
4
 
5
5
  import { PcbArcUtils } from './PcbArcUtils.mjs'
6
+ import { PcbDimensionPrimitiveRenderer } from './PcbDimensionPrimitiveRenderer.mjs'
6
7
  import { PcbEdgeFacingGlyphNormalizer } from './PcbEdgeFacingGlyphNormalizer.mjs'
7
8
  import { PcbEmbeddedFontFaceRenderer } from './PcbEmbeddedFontFaceRenderer.mjs'
8
9
  import { PcbFootprintPrimitiveSelector } from './PcbFootprintPrimitiveSelector.mjs'
@@ -54,6 +55,7 @@ export class PcbSvgRenderer {
54
55
  : regions
55
56
  const vias = pcb.vias || []
56
57
  const pads = pcb.pads || []
58
+ const dimensions = pcb.dimensions || []
57
59
  const components = pcb.components.slice(0, 260)
58
60
  const stackLayers = Array.isArray(pcb.layers) ? pcb.layers : []
59
61
  const primitiveLayers = pcb.primitiveLayers || []
@@ -131,7 +133,8 @@ export class PcbSvgRenderer {
131
133
  ...footprintPrimitives.regions
132
134
  ],
133
135
  vias,
134
- pads
136
+ pads,
137
+ dimensions
135
138
  )
136
139
  const layerMarkup = displayLayers
137
140
  .slice(0, 10)
@@ -376,6 +379,22 @@ export class PcbSvgRenderer {
376
379
  const textMarkup = PcbTextPrimitiveRenderer.render(texts, {
377
380
  semanticContext
378
381
  })
382
+ const dimensionMarkup = PcbDimensionPrimitiveRenderer.buildMarkup(
383
+ dimensions,
384
+ {
385
+ attributes: (dimension, index) =>
386
+ PcbSvgRenderer.#dimensionAttributes(
387
+ dimension,
388
+ PcbSvgRenderer.#primitiveIndex(
389
+ semanticContext,
390
+ 'dimensions',
391
+ dimension,
392
+ index
393
+ ),
394
+ semanticContext
395
+ )
396
+ }
397
+ )
379
398
  const textGeometryMarkup = viewOptions.includeTextGeometrySidecar
380
399
  ? PcbSvgRenderer.#buildTextGeometryMetadataMarkup(
381
400
  texts,
@@ -536,6 +555,7 @@ export class PcbSvgRenderer {
536
555
  '>' +
537
556
  textMarkup +
538
557
  '</g>' +
558
+ dimensionMarkup +
539
559
  '<path class="board-outline board-outline--stroke pcb-layer pcb-layer--edge-cuts" data-layer-name="Edge.Cuts"' +
540
560
  PcbSvgRenderer.#renderDataAttributes({
541
561
  'data-primitive': 'board-outline',
@@ -685,6 +705,7 @@ export class PcbSvgRenderer {
685
705
  regions: (pcb?.regions || []).filter(filter),
686
706
  shapeBasedRegions: (pcb?.shapeBasedRegions || []).filter(filter),
687
707
  texts: (pcb?.texts || []).filter(filter),
708
+ dimensions: (pcb?.dimensions || []).filter(filter),
688
709
  components: (pcb?.components || []).filter(filter)
689
710
  }
690
711
  }
@@ -812,6 +833,9 @@ export class PcbSvgRenderer {
812
833
  vias: PcbSvgRenderer.#objectIndexMap(pcb?.vias || []),
813
834
  pads: PcbSvgRenderer.#objectIndexMap(pcb?.pads || []),
814
835
  texts: PcbSvgRenderer.#objectIndexMap(pcb?.texts || []),
836
+ dimensions: PcbSvgRenderer.#objectIndexMap(
837
+ pcb?.dimensions || []
838
+ ),
815
839
  components: PcbSvgRenderer.#objectIndexMap(
816
840
  pcb?.components || []
817
841
  )
@@ -878,6 +902,12 @@ export class PcbSvgRenderer {
878
902
  pcb?.texts || [],
879
903
  semanticContext
880
904
  ),
905
+ ...PcbSvgRenderer.#semanticMetadataEntries(
906
+ 'dimension',
907
+ 'dimensions',
908
+ pcb?.dimensions || [],
909
+ semanticContext
910
+ ),
881
911
  ...PcbSvgRenderer.#semanticMetadataEntries(
882
912
  'component',
883
913
  'components',
@@ -1137,6 +1167,22 @@ export class PcbSvgRenderer {
1137
1167
  textRole:
1138
1168
  primitiveKind === 'text'
1139
1169
  ? primitive?.role || primitive?.textRole
1170
+ : undefined,
1171
+ dimensionKind:
1172
+ primitiveKind === 'dimension'
1173
+ ? primitive?.kind || 'linear'
1174
+ : undefined,
1175
+ measuredValue:
1176
+ primitiveKind === 'dimension'
1177
+ ? (primitive?.measuredValue ?? undefined)
1178
+ : undefined,
1179
+ angleValue:
1180
+ primitiveKind === 'dimension'
1181
+ ? (primitive?.angleValue ?? undefined)
1182
+ : undefined,
1183
+ text:
1184
+ primitiveKind === 'dimension'
1185
+ ? primitive?.text || undefined
1140
1186
  : undefined
1141
1187
  })
1142
1188
  })
@@ -1193,6 +1239,32 @@ export class PcbSvgRenderer {
1193
1239
  })
1194
1240
  }
1195
1241
 
1242
+ /**
1243
+ * Renders semantic data attributes for one dimension SVG group.
1244
+ * @param {object} dimension Dimension record.
1245
+ * @param {number} index Stable dimension index.
1246
+ * @param {object} semanticContext Semantic lookup context.
1247
+ * @returns {string}
1248
+ */
1249
+ static #dimensionAttributes(dimension, index, semanticContext) {
1250
+ return (
1251
+ PcbSvgRenderer.#semanticAttributes(
1252
+ 'dimension',
1253
+ dimension,
1254
+ index,
1255
+ semanticContext
1256
+ ) +
1257
+ PcbSvgRenderer.#renderDataAttributes({
1258
+ 'data-dimension-kind': dimension?.kind || 'linear',
1259
+ 'data-dimension-name': dimension?.name,
1260
+ 'data-dimension-text': dimension?.text,
1261
+ 'data-measured-value': dimension?.measuredValue,
1262
+ 'data-angle-value': dimension?.angleValue,
1263
+ 'data-unit': dimension?.unit
1264
+ })
1265
+ )
1266
+ }
1267
+
1196
1268
  /**
1197
1269
  * Inserts generated attributes into a simple SVG element string.
1198
1270
  * @param {string} markup SVG element markup.
@@ -1344,6 +1416,7 @@ export class PcbSvgRenderer {
1344
1416
  'vias',
1345
1417
  'pads',
1346
1418
  'texts',
1419
+ 'dimensions',
1347
1420
  'components',
1348
1421
  'regions',
1349
1422
  'shapeBasedRegions'
@@ -1688,6 +1761,7 @@ export class PcbSvgRenderer {
1688
1761
  * @param {{ points?: { x: number, y: number }[], holes?: { x: number, y: number }[][] }[]} regions
1689
1762
  * @param {{ x: number, y: number, diameter: number }[]} vias
1690
1763
  * @param {{ x: number, y: number, sizeTopX?: number, sizeTopY?: number, sizeMidX?: number, sizeMidY?: number, sizeBottomX?: number, sizeBottomY?: number, holeDiameter?: number }[]} pads
1764
+ * @param {{ references?: { x: number, y: number }[], textLocation?: { x: number, y: number } }[]} dimensions
1691
1765
  * @returns {string}
1692
1766
  */
1693
1767
  static #buildViewBox(
@@ -1699,7 +1773,8 @@ export class PcbSvgRenderer {
1699
1773
  arcs,
1700
1774
  regions,
1701
1775
  vias,
1702
- pads
1776
+ pads,
1777
+ dimensions
1703
1778
  ) {
1704
1779
  const xs = [outline.minX, outline.minX + outline.widthMil]
1705
1780
  const ys = [outline.minY, outline.minY + outline.heightMil]
@@ -1743,6 +1818,7 @@ export class PcbSvgRenderer {
1743
1818
  xs.push(pad.x - size.width / 2, pad.x + size.width / 2)
1744
1819
  ys.push(pad.y - size.height / 2, pad.y + size.height / 2)
1745
1820
  }
1821
+ PcbDimensionPrimitiveRenderer.pushExtents(xs, ys, dimensions)
1746
1822
  for (const component of components) {
1747
1823
  const bodyGeometry = PcbSvgRenderer.#footprintSize(
1748
1824
  component.pattern