Back to home page

EIC code displayed by LXR

 
 

    


Warning, /firebird/firebird-ng/src/app/data-pipelines/three-geometry.processor.ts is written in an unsupported language. File is not indexed.

0001 import * as THREE from "three";
0002 import {wildCardCheck} from "../utils/wildcard";
0003 import {editThreeNodeContent, EditThreeNodeRule, clearGeometryEditingFlags} from "../utils/three-geometry-editor";
0004 import {Subdetector} from "../model/subdetector";
0005 
0006 /**
0007  * A typed object that associates a name (or multiple names) with an array of edit rules.
0008  * E.g. { name: "DIRC_14", rules: [ { patterns: [...], ... } ] }
0009  */
0010 export interface DetectorThreeRuleSet {
0011   names?: string[];
0012   name?: string;
0013   rules: EditThreeNodeRule[];
0014 }
0015 
0016 /**
0017  * Converts a raw JSON/JSONC array into typed DetectorThreeRuleSet objects.
0018  * If an EditThreeNodeRule has "materialJson", we parse it using THREE.MaterialLoader.
0019  */
0020 export function ruleSetsFromObj(obj: any): DetectorThreeRuleSet[] {
0021   // Not an array => return empty
0022   if (!Array.isArray(obj)) {
0023     console.warn('ruleSetsFromObj: top-level object is not an array. Returning empty.');
0024     return [];
0025   }
0026 
0027   // Create a single MaterialLoader we can reuse for all materialJson objects
0028   const materialLoader = new THREE.MaterialLoader();
0029 
0030   return obj.map((item: any) => {
0031     // Ensure we have a rules array
0032     if (!item.rules || !Array.isArray(item.rules)) {
0033       console.warn('ruleSetsFromObj: missing or invalid "rules" array in item:', item);
0034       return { rules: [] };
0035     }
0036 
0037     // Convert each rule
0038     const convertedRules: EditThreeNodeRule[] = item.rules.map((r: any) => {
0039       const rule: EditThreeNodeRule = { ...r };
0040 
0041       // 1) Convert a color from string hex "0xabcdef" => number
0042       if (typeof rule.color === 'string') {
0043         rule.color = parseInt(rule.color, 16);
0044       }
0045 
0046       // 2) If there's "materialJson", parse it using THREE.MaterialLoader
0047       if (r.materialJson && typeof r.materialJson === 'object') {
0048         try {
0049           // Convert raw JSON to real material
0050           const loadedMaterial = materialLoader.parse(r.materialJson);
0051           rule.material = loadedMaterial;
0052         } catch (err) {
0053           console.error('Failed to parse materialJson:', err, r.materialJson);
0054         }
0055       }
0056 
0057       return rule;
0058     });
0059 
0060     return {
0061       names: item.names,
0062       name: item.name,
0063       rules: convertedRules,
0064     };
0065   });
0066 }
0067 
0068 
0069 /**
0070  * Matches which set of rules should be applied to which detectors
0071  *
0072  * - Detectors are matched based on their `sourceGeometryName` against the names specified in the rulesets.
0073  * - Rule lists are matched to detectors in the order they appear in the rulesets
0074  * - Once a rule is applied to a detector, that detector is excluded from further rule matching, ensuring each detector is processed only once.
0075  * - If both `names` and `name` are provided in a ruleset, the function treats it as a user error in JSON rule editing but processes both without raising an exception.
0076  * - If a ruleset contains a wildcard name (`"*"`), it will apply its rules to any detectors not already matched by previous rulesets. So it should be placed in
0077  *
0078  * @param {Subdetector[]} detectors - The list of detectors to which the rules will be applied.
0079  * @param {DetectorThreeRuleSet[]} ruleSets - The set of rules to be applied, processed sequentially.
0080  * @return {Map<Subdetector, EditThreeNodeRule[]>} - A map associating each detector with an array of the rules applied to it.
0081  */
0082 export function matchRulesToDetectors(ruleSets: DetectorThreeRuleSet[], detectors: Subdetector[]): Map<Subdetector, EditThreeNodeRule[]> {
0083   const unassignedDetectors = new Set(detectors);
0084   const detectorRulesMap = new Map<Subdetector, EditThreeNodeRule[]>();
0085 
0086   for(let ruleSet of ruleSets) {
0087     const targets = new Set<Subdetector>();
0088     let names = new Set<string>(ruleSet.names || []);
0089 
0090     // Handle possible user error where both 'name' and 'names' are provided.
0091     if (ruleSet.name) {
0092       names.add(ruleSet.name);
0093     }
0094 
0095     for(let name of names) {
0096       for(let det of unassignedDetectors) {
0097         if (wildCardCheck(det.sourceGeometryName, name)) {
0098           targets.add(det);
0099           detectorRulesMap.set(det, ruleSet.rules || []);
0100           unassignedDetectors.delete(det);  // Move deletion here to optimize
0101         }
0102       }
0103     }
0104   }
0105 
0106   return detectorRulesMap;
0107 }
0108 
0109 export class ThreeGeometryProcessor {
0110 
0111 
0112   constructor() {
0113 
0114   }
0115 
0116   public processRuleSets(ruleSets: DetectorThreeRuleSet[], detectors: Subdetector[]) {
0117     console.log(`[processRuleSets] Applying ${ruleSets.length} theme rules...`)
0118     const totalTimePerfMessage = "[processRuleSets] Time applying rules";
0119     console.time(totalTimePerfMessage);
0120     let detRulesMap = matchRulesToDetectors(ruleSets, detectors);
0121     for (let [detector, ruleSet] of detRulesMap) {
0122       // Some performance metrics
0123       const start = performance.now();
0124 
0125       // Clear geometry editing flags before processing this detector's rules
0126       // This ensures "the rest" rules work correctly within each detector's ruleset
0127       clearGeometryEditingFlags(detector.geometry);
0128 
0129       // Actually apply rules
0130       for(let rule of ruleSet) {
0131         editThreeNodeContent(detector.geometry, rule);
0132       }
0133 
0134       // Check the rule didn't take too long
0135       const end = performance.now();
0136       const elapsed = end - start;
0137       if(elapsed > 500) {
0138         console.log(`[processRuleSet] Applying rules took >0.5s: ${elapsed.toFixed(1)} for ${detector.name}`);
0139       }
0140     }
0141     console.timeEnd(totalTimePerfMessage);
0142   }
0143 }