pcb-scene3d-viewer 1.1.21 → 1.1.22

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,242 @@
1
+ import { PcbScene3dExternalCompanionFallback } from './PcbScene3dExternalCompanionFallback.mjs'
2
+
3
+ /**
4
+ * Lifts authored model placements that sit on companion fallback bases.
5
+ */
6
+ export class PcbScene3dCompanionBasePlacementAdjuster {
7
+ static #ENVELOPE_MARGIN_RATIO = 0.25
8
+ static #ENVELOPE_MIN_MARGIN_MIL = 20
9
+ static #POSITION_EPSILON = 1e-6
10
+
11
+ /**
12
+ * Returns a scene copy with placements seated on companion fallback bases.
13
+ * @param {object} sceneDescription Scene description.
14
+ * @returns {object}
15
+ */
16
+ static adjust(sceneDescription) {
17
+ const bases =
18
+ PcbScene3dCompanionBasePlacementAdjuster.#companionBases(
19
+ sceneDescription
20
+ )
21
+ if (!bases.length) {
22
+ return sceneDescription
23
+ }
24
+
25
+ return {
26
+ ...sceneDescription,
27
+ externalPlacements:
28
+ PcbScene3dCompanionBasePlacementAdjuster.#adjustPlacements(
29
+ sceneDescription?.externalPlacements,
30
+ bases
31
+ ),
32
+ staticBodyPlacements:
33
+ PcbScene3dCompanionBasePlacementAdjuster.#adjustPlacements(
34
+ sceneDescription?.staticBodyPlacements,
35
+ bases
36
+ )
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Resolves companion fallback bases from components in one scene.
42
+ * @param {object} sceneDescription Scene description.
43
+ * @returns {object[]}
44
+ */
45
+ static #companionBases(sceneDescription) {
46
+ return (
47
+ Array.isArray(sceneDescription?.components)
48
+ ? sceneDescription.components
49
+ : []
50
+ )
51
+ .filter((component) =>
52
+ PcbScene3dExternalCompanionFallback.shouldKeepFallback(
53
+ sceneDescription,
54
+ component
55
+ )
56
+ )
57
+ .map((component) =>
58
+ PcbScene3dCompanionBasePlacementAdjuster.#buildBase(component)
59
+ )
60
+ .filter(Boolean)
61
+ }
62
+
63
+ /**
64
+ * Builds one companion base descriptor from a component.
65
+ * @param {object} component Scene component.
66
+ * @returns {object | null}
67
+ */
68
+ static #buildBase(component) {
69
+ const size = component?.body?.sizeMil || {}
70
+ const heightMil = Number(size.height || 0)
71
+ const widthMil = Number(size.width || 0)
72
+ const depthMil = Number(size.depth || 0)
73
+ if (!(heightMil > 0) || !(widthMil > 0) || !(depthMil > 0)) {
74
+ return null
75
+ }
76
+
77
+ return {
78
+ designator: String(component?.designator || '').trim(),
79
+ mountSide: String(component?.mountSide || 'top').toLowerCase(),
80
+ positionMil: {
81
+ x: Number(component?.positionMil?.x || 0),
82
+ y: Number(component?.positionMil?.y || 0),
83
+ z: Number(component?.positionMil?.z || 0)
84
+ },
85
+ rotationDeg: Number(component?.rotationDeg || 0),
86
+ widthMil,
87
+ depthMil,
88
+ heightMil,
89
+ signedLiftMil:
90
+ (PcbScene3dCompanionBasePlacementAdjuster.#isBottomSide(
91
+ component?.mountSide
92
+ )
93
+ ? -1
94
+ : 1) * heightMil
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Adjusts one placement list against all companion bases.
100
+ * @param {object[] | undefined} placements Original placements.
101
+ * @param {object[]} bases Companion bases.
102
+ * @returns {object[]}
103
+ */
104
+ static #adjustPlacements(placements, bases) {
105
+ return (Array.isArray(placements) ? placements : []).map((placement) =>
106
+ PcbScene3dCompanionBasePlacementAdjuster.#adjustPlacement(
107
+ placement,
108
+ bases
109
+ )
110
+ )
111
+ }
112
+
113
+ /**
114
+ * Adjusts one placement when it overlaps a companion base.
115
+ * @param {object} placement Original placement.
116
+ * @param {object[]} bases Companion bases.
117
+ * @returns {object}
118
+ */
119
+ static #adjustPlacement(placement, bases) {
120
+ const base = bases.find((candidate) =>
121
+ PcbScene3dCompanionBasePlacementAdjuster.#isPlacementOnBase(
122
+ placement,
123
+ candidate
124
+ )
125
+ )
126
+ if (!base) {
127
+ return placement
128
+ }
129
+
130
+ return {
131
+ ...placement,
132
+ positionMil: {
133
+ ...(placement?.positionMil || {}),
134
+ z: PcbScene3dCompanionBasePlacementAdjuster.#roundMil(
135
+ Number(placement?.positionMil?.z || 0) + base.signedLiftMil
136
+ )
137
+ }
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Checks whether a placement should be lifted onto one companion base.
143
+ * @param {object} placement Candidate placement.
144
+ * @param {object} base Companion base descriptor.
145
+ * @returns {boolean}
146
+ */
147
+ static #isPlacementOnBase(placement, base) {
148
+ if (
149
+ !PcbScene3dCompanionBasePlacementAdjuster.#isSameSide(
150
+ placement,
151
+ base
152
+ )
153
+ ) {
154
+ return false
155
+ }
156
+
157
+ const local =
158
+ PcbScene3dCompanionBasePlacementAdjuster.#toBaseLocalPosition(
159
+ placement,
160
+ base
161
+ )
162
+ const envelopeMarginMil =
163
+ PcbScene3dCompanionBasePlacementAdjuster.#envelopeMarginMil(base)
164
+
165
+ return (
166
+ Math.abs(local.x) <= base.widthMil / 2 + envelopeMarginMil &&
167
+ Math.abs(local.y) <= base.depthMil / 2 + envelopeMarginMil
168
+ )
169
+ }
170
+
171
+ /**
172
+ * Checks whether a placement and base are on the same board side.
173
+ * @param {object} placement Candidate placement.
174
+ * @param {object} base Companion base descriptor.
175
+ * @returns {boolean}
176
+ */
177
+ static #isSameSide(placement, base) {
178
+ return (
179
+ String(placement?.mountSide || 'top').toLowerCase() ===
180
+ String(base?.mountSide || 'top').toLowerCase()
181
+ )
182
+ }
183
+
184
+ /**
185
+ * Converts a placement anchor into a companion-base local frame.
186
+ * @param {object} placement Candidate placement.
187
+ * @param {object} base Companion base descriptor.
188
+ * @returns {{ x: number, y: number }}
189
+ */
190
+ static #toBaseLocalPosition(placement, base) {
191
+ const dx =
192
+ Number(placement?.positionMil?.x || 0) -
193
+ Number(base?.positionMil?.x || 0)
194
+ const dy =
195
+ Number(placement?.positionMil?.y || 0) -
196
+ Number(base?.positionMil?.y || 0)
197
+ const radians = -((Number(base?.rotationDeg || 0) * Math.PI) / 180)
198
+ const cos = Math.cos(radians)
199
+ const sin = Math.sin(radians)
200
+
201
+ return {
202
+ x: dx * cos - dy * sin,
203
+ y: dx * sin + dy * cos
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Resolves loose matching margin for authored parts near a base edge.
209
+ * @param {object} base Companion base descriptor.
210
+ * @returns {number}
211
+ */
212
+ static #envelopeMarginMil(base) {
213
+ return Math.max(
214
+ PcbScene3dCompanionBasePlacementAdjuster.#ENVELOPE_MIN_MARGIN_MIL,
215
+ Math.min(Number(base?.widthMil || 0), Number(base?.depthMil || 0)) *
216
+ PcbScene3dCompanionBasePlacementAdjuster.#ENVELOPE_MARGIN_RATIO
217
+ )
218
+ }
219
+
220
+ /**
221
+ * Checks whether a mount side is bottom.
222
+ * @param {string | undefined} mountSide Mount side.
223
+ * @returns {boolean}
224
+ */
225
+ static #isBottomSide(mountSide) {
226
+ return String(mountSide || 'top').toLowerCase() === 'bottom'
227
+ }
228
+
229
+ /**
230
+ * Rounds one mil coordinate.
231
+ * @param {number} value Candidate value.
232
+ * @returns {number}
233
+ */
234
+ static #roundMil(value) {
235
+ const rounded =
236
+ Math.round(
237
+ Number(value || 0) /
238
+ PcbScene3dCompanionBasePlacementAdjuster.#POSITION_EPSILON
239
+ ) * PcbScene3dCompanionBasePlacementAdjuster.#POSITION_EPSILON
240
+ return Object.is(rounded, -0) ? 0 : rounded
241
+ }
242
+ }
@@ -1,3 +1,5 @@
1
+ import { PcbScene3dFallbackVisibility } from './PcbScene3dFallbackVisibility.mjs'
2
+
1
3
  /**
2
4
  * Applies per-component hidden state on top of existing 3D visibility toggles.
3
5
  */
@@ -46,7 +48,7 @@ export class PcbScene3dComponentVisibility {
46
48
 
47
49
  /**
48
50
  * Applies component visibility to all selectable render roots.
49
- * @param {{ selectionRoots?: Map<string, Set<any>>, hiddenDesignators?: Set<string>, fallbackBodyRoots?: Map<string, Set<any>>, loadedExternalModelDesignators?: Set<string>, modelSearchExternalModelRoots?: Set<any>, toggles?: { 'external-models'?: boolean, 'fallback-bodies'?: boolean, 'model-search-models'?: boolean }, hasLoadedBoardAssemblyModel?: boolean }} state Visibility state.
51
+ * @param {{ selectionRoots?: Map<string, Set<any>>, selectedDesignator?: string, hiddenDesignators?: Set<string>, fallbackBodyRoots?: Map<string, Set<any>>, loadedExternalModelDesignators?: Set<string>, modelSearchExternalModelRoots?: Set<any>, toggles?: { 'external-models'?: boolean, 'fallback-bodies'?: boolean, 'model-search-models'?: boolean }, hasLoadedBoardAssemblyModel?: boolean }} state Visibility state.
50
52
  * @returns {void}
51
53
  */
52
54
  static apply(state) {
@@ -55,6 +57,11 @@ export class PcbScene3dComponentVisibility {
55
57
  return
56
58
  }
57
59
 
60
+ const selectedVariantGroupKeys =
61
+ PcbScene3dComponentVisibility.#selectedVariantGroupKeys(
62
+ selectionRoots,
63
+ state?.selectedDesignator
64
+ )
58
65
  selectionRoots.forEach((roots, designator) => {
59
66
  roots?.forEach?.((rootObject) => {
60
67
  if (!rootObject) {
@@ -66,6 +73,12 @@ export class PcbScene3dComponentVisibility {
66
73
  state?.hiddenDesignators,
67
74
  designator
68
75
  ) &&
76
+ !PcbScene3dComponentVisibility.#isUnselectedVariantSibling(
77
+ rootObject,
78
+ designator,
79
+ state?.selectedDesignator,
80
+ selectedVariantGroupKeys
81
+ ) &&
69
82
  PcbScene3dComponentVisibility.#resolveRootVisible(
70
83
  state,
71
84
  designator,
@@ -75,6 +88,75 @@ export class PcbScene3dComponentVisibility {
75
88
  })
76
89
  }
77
90
 
91
+ /**
92
+ * Resolves variant groups represented by the selected component roots.
93
+ * @param {Map<string, Set<any>>} selectionRoots Registered selectable roots.
94
+ * @param {string | undefined} selectedDesignator Current selection.
95
+ * @returns {Set<string>}
96
+ */
97
+ static #selectedVariantGroupKeys(selectionRoots, selectedDesignator) {
98
+ const selectedKey =
99
+ PcbScene3dComponentVisibility.#normalizeDesignator(
100
+ selectedDesignator
101
+ )
102
+ const groups = new Set()
103
+ if (!selectedKey) {
104
+ return groups
105
+ }
106
+
107
+ selectionRoots.get(selectedKey)?.forEach?.((rootObject) => {
108
+ const groupKey =
109
+ PcbScene3dComponentVisibility.#variantGroupKey(rootObject)
110
+ if (groupKey) {
111
+ groups.add(groupKey)
112
+ }
113
+ })
114
+ return groups
115
+ }
116
+
117
+ /**
118
+ * Checks whether one selectable root is an alternate of the selection.
119
+ * @param {any} rootObject Selectable root.
120
+ * @param {string} designator Root designator.
121
+ * @param {string | undefined} selectedDesignator Current selection.
122
+ * @param {Set<string>} selectedVariantGroupKeys Selected variant groups.
123
+ * @returns {boolean}
124
+ */
125
+ static #isUnselectedVariantSibling(
126
+ rootObject,
127
+ designator,
128
+ selectedDesignator,
129
+ selectedVariantGroupKeys
130
+ ) {
131
+ const selectedKey =
132
+ PcbScene3dComponentVisibility.#normalizeDesignator(
133
+ selectedDesignator
134
+ )
135
+ if (!selectedKey || !selectedVariantGroupKeys.size) {
136
+ return false
137
+ }
138
+
139
+ if (
140
+ PcbScene3dComponentVisibility.#normalizeDesignator(designator) ===
141
+ selectedKey
142
+ ) {
143
+ return false
144
+ }
145
+
146
+ const groupKey =
147
+ PcbScene3dComponentVisibility.#variantGroupKey(rootObject)
148
+ return Boolean(groupKey && selectedVariantGroupKeys.has(groupKey))
149
+ }
150
+
151
+ /**
152
+ * Reads the authored co-located variant group key from a render root.
153
+ * @param {any} rootObject Render root.
154
+ * @returns {string}
155
+ */
156
+ static #variantGroupKey(rootObject) {
157
+ return String(rootObject?.userData?.scene3dVariantGroupKey || '').trim()
158
+ }
159
+
78
160
  /**
79
161
  * Resolves root-level visibility before selected-component hiding.
80
162
  * @param {{ fallbackBodyRoots?: Map<string, Set<any>>, loadedExternalModelDesignators?: Set<string>, modelSearchExternalModelRoots?: Set<any>, toggles?: { 'external-models'?: boolean, 'fallback-bodies'?: boolean, 'model-search-models'?: boolean }, hasLoadedBoardAssemblyModel?: boolean }} state Visibility state.
@@ -92,7 +174,8 @@ export class PcbScene3dComponentVisibility {
92
174
  ) {
93
175
  return PcbScene3dComponentVisibility.#resolveFallbackVisible(
94
176
  state,
95
- designator
177
+ designator,
178
+ rootObject
96
179
  )
97
180
  }
98
181
 
@@ -110,14 +193,27 @@ export class PcbScene3dComponentVisibility {
110
193
  * Resolves fallback root visibility from current detail toggles.
111
194
  * @param {{ loadedExternalModelDesignators?: Set<string>, toggles?: { 'external-models'?: boolean, 'fallback-bodies'?: boolean }, hasLoadedBoardAssemblyModel?: boolean }} state Visibility state.
112
195
  * @param {string} designator Component designator.
196
+ * @param {any} rootObject Render root.
113
197
  * @returns {boolean}
114
198
  */
115
- static #resolveFallbackVisible(state, designator) {
199
+ static #resolveFallbackVisible(state, designator, rootObject) {
116
200
  const boardAssemblyActive =
117
201
  Boolean(state?.hasLoadedBoardAssemblyModel) &&
118
202
  Boolean(state?.toggles?.['external-models'])
119
- const showFallbackBodies =
120
- Boolean(state?.toggles?.['fallback-bodies']) && !boardAssemblyActive
203
+ if (boardAssemblyActive) {
204
+ return false
205
+ }
206
+
207
+ if (
208
+ PcbScene3dFallbackVisibility.shouldKeepExternalCompanion(
209
+ rootObject,
210
+ state?.toggles
211
+ )
212
+ ) {
213
+ return true
214
+ }
215
+
216
+ const showFallbackBodies = Boolean(state?.toggles?.['fallback-bodies'])
121
217
  const hideForLoadedExternal =
122
218
  Boolean(state?.toggles?.['external-models']) &&
123
219
  state?.loadedExternalModelDesignators?.has?.(
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Detects fallback bodies that should remain visible as companions for partial
3
+ * external model placements.
4
+ */
5
+ export class PcbScene3dExternalCompanionFallback {
6
+ /**
7
+ * Checks whether a component fallback body should remain visible as the
8
+ * package companion for a partial embedded external model.
9
+ * @param {{ externalPlacements?: object[], staticBodyPlacements?: object[] }} sceneDescription Scene data.
10
+ * @param {{ designator?: string, mountSide?: string, positionMil?: { x?: number, y?: number }, body?: { sizeMil?: { width?: number, depth?: number } } }} component Component scene entry.
11
+ * @returns {boolean}
12
+ */
13
+ static shouldKeepFallback(sceneDescription, component) {
14
+ const designator =
15
+ PcbScene3dExternalCompanionFallback.#normalizedDesignator(
16
+ component?.designator
17
+ )
18
+ if (!designator) {
19
+ return false
20
+ }
21
+
22
+ if (
23
+ PcbScene3dExternalCompanionFallback.#hasAuthoredCompanionBase(
24
+ sceneDescription,
25
+ component
26
+ )
27
+ ) {
28
+ return false
29
+ }
30
+
31
+ return PcbScene3dExternalCompanionFallback.#externalPlacements(
32
+ sceneDescription
33
+ ).some(
34
+ (placement) =>
35
+ PcbScene3dExternalCompanionFallback.#normalizedDesignator(
36
+ placement?.designator
37
+ ) === designator &&
38
+ PcbScene3dExternalCompanionFallback.#isPartialEmbeddedPlacement(
39
+ placement
40
+ )
41
+ )
42
+ }
43
+
44
+ /**
45
+ * Checks whether an authored static body already provides the package base
46
+ * for one partial embedded placement.
47
+ * @param {{ staticBodyPlacements?: object[] }} sceneDescription Scene data.
48
+ * @param {{ mountSide?: string, positionMil?: { x?: number, y?: number }, body?: { sizeMil?: { width?: number, depth?: number } } }} component Component scene entry.
49
+ * @returns {boolean}
50
+ */
51
+ static #hasAuthoredCompanionBase(sceneDescription, component) {
52
+ return PcbScene3dExternalCompanionFallback.#staticBodyPlacements(
53
+ sceneDescription
54
+ ).some(
55
+ (placement) =>
56
+ PcbScene3dExternalCompanionFallback.#isSameSide(
57
+ placement,
58
+ component
59
+ ) &&
60
+ PcbScene3dExternalCompanionFallback.#isRenderableBase(
61
+ placement
62
+ ) &&
63
+ PcbScene3dExternalCompanionFallback.#isNearComponent(
64
+ placement,
65
+ component
66
+ )
67
+ )
68
+ }
69
+
70
+ /**
71
+ * Resolves normalized external placements from one scene description.
72
+ * @param {{ externalPlacements?: object[] }} sceneDescription Scene data.
73
+ * @returns {object[]}
74
+ */
75
+ static #externalPlacements(sceneDescription) {
76
+ return Array.isArray(sceneDescription?.externalPlacements)
77
+ ? sceneDescription.externalPlacements
78
+ : []
79
+ }
80
+
81
+ /**
82
+ * Resolves normalized static body placements from one scene description.
83
+ * @param {{ staticBodyPlacements?: object[] }} sceneDescription Scene data.
84
+ * @returns {object[]}
85
+ */
86
+ static #staticBodyPlacements(sceneDescription) {
87
+ return Array.isArray(sceneDescription?.staticBodyPlacements)
88
+ ? sceneDescription.staticBodyPlacements
89
+ : []
90
+ }
91
+
92
+ /**
93
+ * Checks whether a placement and component share a board side.
94
+ * @param {object} placement Static body placement.
95
+ * @param {object} component Scene component.
96
+ * @returns {boolean}
97
+ */
98
+ static #isSameSide(placement, component) {
99
+ return (
100
+ String(placement?.mountSide || 'top').toLowerCase() ===
101
+ String(component?.mountSide || 'top').toLowerCase()
102
+ )
103
+ }
104
+
105
+ /**
106
+ * Checks whether one static body can act as a package base.
107
+ * @param {object} placement Static body placement.
108
+ * @returns {boolean}
109
+ */
110
+ static #isRenderableBase(placement) {
111
+ const geometry = placement?.geometry || {}
112
+ return (
113
+ String(geometry?.kind || '').toLowerCase() === 'extruded-polygon' &&
114
+ PcbScene3dExternalCompanionFallback.#geometrySpan(geometry).width >
115
+ 0 &&
116
+ PcbScene3dExternalCompanionFallback.#geometrySpan(geometry).depth >
117
+ 0
118
+ )
119
+ }
120
+
121
+ /**
122
+ * Checks whether one authored base is close enough to own a component base.
123
+ * @param {object} placement Static body placement.
124
+ * @param {object} component Scene component.
125
+ * @returns {boolean}
126
+ */
127
+ static #isNearComponent(placement, component) {
128
+ const span = PcbScene3dExternalCompanionFallback.#geometrySpan(
129
+ placement?.geometry
130
+ )
131
+ const componentSize = component?.body?.sizeMil || {}
132
+ const threshold = Math.max(
133
+ 30,
134
+ Number(span.width || 0) / 2,
135
+ Number(span.depth || 0) / 2,
136
+ Number(componentSize.width || 0) / 2,
137
+ Number(componentSize.depth || 0) / 2
138
+ )
139
+ const dx =
140
+ Number(placement?.positionMil?.x || 0) -
141
+ Number(component?.positionMil?.x || 0)
142
+ const dy =
143
+ Number(placement?.positionMil?.y || 0) -
144
+ Number(component?.positionMil?.y || 0)
145
+
146
+ return Math.hypot(dx, dy) <= threshold
147
+ }
148
+
149
+ /**
150
+ * Resolves width and depth for one polygon geometry.
151
+ * @param {{ verticesMil?: { x?: number, y?: number }[] } | undefined} geometry Static geometry.
152
+ * @returns {{ width: number, depth: number }}
153
+ */
154
+ static #geometrySpan(geometry) {
155
+ const vertices = Array.isArray(geometry?.verticesMil)
156
+ ? geometry.verticesMil
157
+ : []
158
+ if (vertices.length < 3) {
159
+ return { width: 0, depth: 0 }
160
+ }
161
+
162
+ const xs = vertices.map((vertex) => Number(vertex?.x || 0))
163
+ const ys = vertices.map((vertex) => Number(vertex?.y || 0))
164
+
165
+ return {
166
+ width: Math.max(...xs) - Math.min(...xs),
167
+ depth: Math.max(...ys) - Math.min(...ys)
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Checks for embedded external placements that represent a sub-body, not a
173
+ * complete replacement for the procedural component body.
174
+ * @param {object} placement External model placement.
175
+ * @returns {boolean}
176
+ */
177
+ static #isPartialEmbeddedPlacement(placement) {
178
+ const projection = placement?.projection || {}
179
+ const bounds = projection?.boundsMil || {}
180
+
181
+ return (
182
+ String(placement?.externalModel?.origin || '').toLowerCase() ===
183
+ 'embedded' &&
184
+ String(projection?.source || '').toLowerCase() ===
185
+ 'model-anchor-fallback' &&
186
+ Math.max(
187
+ Number(bounds.width || 0),
188
+ Number(bounds.depth || 0),
189
+ Number(bounds.height || 0)
190
+ ) <= 0
191
+ )
192
+ }
193
+
194
+ /**
195
+ * Normalizes one designator for component/external placement matching.
196
+ * @param {unknown} designator Candidate designator.
197
+ * @returns {string}
198
+ */
199
+ static #normalizedDesignator(designator) {
200
+ return String(designator || '').trim()
201
+ }
202
+ }
@@ -293,6 +293,12 @@ export class PcbScene3dExternalModels {
293
293
  designator,
294
294
  sourceType: 'external-model'
295
295
  }
296
+ const variantGroupKey = String(
297
+ placement?.coLocatedVariantGroupKey || ''
298
+ ).trim()
299
+ if (variantGroupKey) {
300
+ wrapperGroup.userData.scene3dVariantGroupKey = variantGroupKey
301
+ }
296
302
  adjustmentGroup.userData.scene3dAdjustmentTarget = true
297
303
  adjustmentGroup.userData.scene3dAdjustmentDesignator = designator
298
304
  adjustmentGroup.userData.scene3dAdjustmentBaseline =