Detects data modality from dimension information.
Consolidates modality detection logic that was duplicated across analyzers. Uses dimension roles and count to determine appropriate processing approach.
162{
163 if (dimensions.empty()) {
164 return DataModality::UNKNOWN;
165 }
166
167 size_t time_dims = 0, spatial_dims = 0, channel_dims = 0, frequency_dims = 0, depth_dims = 0, custom_dims = 0;
168 size_t total_spatial_elements = 1;
169 size_t total_channels = 0;
170
171 for (const auto& dim : dimensions) {
172 if (dim.grouping) {
173 switch (dim.role) {
174 case DataDimension::Role::POSITION:
175 return DataModality::VERTEX_POSITIONS_3D;
176 case DataDimension::Role::NORMAL:
177 return DataModality::VERTEX_NORMALS_3D;
178 case DataDimension::Role::TANGENT:
179 case DataDimension::Role::BITANGENT:
180 return DataModality::VERTEX_TANGENTS_3D;
181 case DataDimension::Role::UV:
182 return DataModality::TEXTURE_COORDS_2D;
183 case DataDimension::Role::COLOR:
184 if (dim.grouping->count == 3)
185 return DataModality::VERTEX_COLORS_RGB;
186 if (dim.grouping->count == 4)
187 return DataModality::VERTEX_COLORS_RGBA;
188 break;
189 default:
190 if (dim.grouping->count == 16)
191 return DataModality::TRANSFORMATION_MATRIX;
192 break;
193 }
194 }
195 }
196
197 for (const auto& dim : dimensions) {
198 switch (dim.role) {
199 case DataDimension::Role::TIME:
200 time_dims++;
201 break;
202 case DataDimension::Role::SPATIAL_X:
203 case DataDimension::Role::SPATIAL_Y:
204 case DataDimension::Role::SPATIAL_Z:
205 spatial_dims++;
206 total_spatial_elements *= dim.size;
207 break;
208 case DataDimension::Role::CHANNEL:
209 channel_dims++;
210 total_channels += dim.size;
211 break;
212 case DataDimension::Role::FREQUENCY:
213 frequency_dims++;
214 break;
215 case DataDimension::Role::DEPTH:
216 depth_dims++;
217 break;
218 case DataDimension::Role::CUSTOM:
219 default:
220 custom_dims++;
221 break;
222 }
223 }
224
225 if (time_dims == 1 && spatial_dims == 0 && frequency_dims == 0) {
226 if (channel_dims == 0) {
227 return DataModality::AUDIO_1D;
228 }
229 if (channel_dims == 1) {
230 return (total_channels <= 1) ? DataModality::AUDIO_1D : DataModality::AUDIO_MULTICHANNEL;
231 }
232 return DataModality::AUDIO_MULTICHANNEL;
233 }
234
235 if (time_dims >= 1 && frequency_dims >= 1) {
236 if (spatial_dims == 0 && channel_dims <= 1) {
237 return DataModality::SPECTRAL_2D;
238 }
239 return DataModality::TENSOR_ND;
240 }
241
242 if (spatial_dims >= 2 && time_dims == 0) {
243 if (spatial_dims == 2) {
244 if (channel_dims == 0) {
245 return DataModality::IMAGE_2D;
246 }
247 if (channel_dims == 1 && total_channels >= 3) {
248 return DataModality::IMAGE_COLOR;
249 }
250 return DataModality::IMAGE_2D;
251 }
252
253 if (spatial_dims == 3) {
254 return DataModality::VOLUMETRIC_3D;
255 }
256 }
257
258 if (depth_dims == 1 && spatial_dims == 2) {
259 return time_dims >= 1
260 ? DataModality::VIDEO_DEPTH
261 : DataModality::DEPTH_MAP;
262 }
263
264 if (time_dims >= 1 && spatial_dims >= 2) {
265 if (spatial_dims == 2) {
266 if (channel_dims == 0 || (channel_dims == 1 && total_channels <= 1)) {
267 return DataModality::VIDEO_GRAYSCALE;
268 }
269
270 return DataModality::VIDEO_COLOR;
271 }
272 return DataModality::TENSOR_ND;
273 }
274
275 if (spatial_dims == 2 && time_dims == 0 && channel_dims >= 1) {
276 if (total_spatial_elements >= 64 && total_channels >= 1) {
277 return DataModality::TEXTURE_2D;
278 }
279 }
280
281 return DataModality::TENSOR_ND;
282}