Back to home page

EIC code displayed by LXR

 
 

    


Warning, /firebird/firebird-ng/src/lib-root-geometry/root-geo-edit.ts is written in an unsupported language. File is not indexed.

0001 import {
0002   GeoNodeWalkCallback,
0003   getGeoNodesByLevel,
0004   walkGeoNodes
0005 } from "./root-geo-navigation";
0006 import {wildCardCheck} from "../app/utils/wildcard";
0007 import {GeoAttBits, setGeoBit, toggleGeoBit} from "./root-geo-attribute-bits";
0008 
0009 
0010 export enum EditActions {
0011   Nothing,          /** Do not remove this or other nodes */
0012   Remove,           /** Removes this node from parent */
0013   RemoveSiblings,   /** Remove all sibling nodes and leave only this node */
0014   RemoveChildren,   /** Remove all child nodes */
0015   RemoveBySubLevel, /** Remove all nodes below N levels */
0016   SetGeoBit,        /** Set certain Root GeoAtt bit */
0017   UnsetGeoBit,      /** Unset certain ROOT GeoAtt bit */
0018   ToggleGeoBit      /** Toggle certain ROOT GeoAtt bit */
0019 }
0020 
0021 /**
0022  * Defines editing rules for geographic nodes based on a pattern.
0023  */
0024 export class GeoNodeEditRule {
0025   public pattern: string = '';
0026   public action?: EditActions = EditActions.Nothing;
0027   public pruneSubLevel?: number = Infinity;
0028 
0029   /** Used only if action is one of SetGeoBit, UnsetGeoBit or ToggleGeoBit */
0030   public geoBit?:GeoAttBits;
0031 
0032   public childrenRules?: GeoNodeEditRule[] = [];
0033   public childrenRulesMaxLevel?: number = Infinity;
0034 }
0035 
0036 
0037 /**
0038  * Edits ROOT Geometry nodes based on specified rules. This function walks through each node,
0039  * applying transformation rules such as removing nodes or modifying node arrays based on provided patterns.
0040  *
0041  * @param {any} topNode - The top node of the geometry tree to edit.
0042  * @param {GeoNodeEditRule[]} rules - An array of rules defining how nodes should be edited.
0043  * @param {number} [maxLevel=Infinity] - The maximum level of the node tree to traverse.
0044  * @returns {any[]} An array of objects detailing nodes that were postponed for processing.
0045  */
0046 export function editGeoNodes(topNode: any, rules: GeoNodeEditRule[], maxLevel:number=Infinity): any[] {
0047   let postponedProcessing: {node: any, fullPath: string, rule: GeoNodeEditRule}[] = [];
0048 
0049   let tmpRules = [...rules];
0050 
0051   // Define a callback using the GeoNodeWalkCallback type
0052   const collectNodes: GeoNodeWalkCallback = (node, nodeFullPath, level) => {
0053     for(const rule of tmpRules) {
0054 
0055       if(nodeFullPath === undefined) {
0056         console.log(`nodeFullPath == undefined`);
0057       }
0058 
0059       if(rule?.pattern === undefined) {
0060         console.log(`rule?.pattern == undefined ${rule}`);
0061       }
0062 
0063       // Does the node fulfill the rule?
0064       if(wildCardCheck(nodeFullPath, rule.pattern)) {
0065 
0066         // This rule has subnode rules
0067         if(rule.childrenRules?.length) {
0068           // Invoke first children rules
0069           editGeoNodes(node, rule.childrenRules, rule.childrenRulesMaxLevel ?? Infinity);
0070         }
0071 
0072         // Remove this geo node
0073         if(rule.action === EditActions.Remove) {
0074           removeGeoNode(node);
0075           return false;  // Don't go through children
0076         }
0077 
0078         // Remove all daughters
0079         if(rule.action === EditActions.RemoveChildren) {
0080           removeChildren(node);
0081           return false;          // don't process children
0082         }
0083 
0084         // (!) All next actions may need to process children
0085         if(rule.action === EditActions.RemoveSiblings || rule.action === EditActions.RemoveBySubLevel) {
0086           // Add a node to matches to process them after
0087           postponedProcessing.push({ node: node, fullPath: nodeFullPath, rule: rule });
0088         }
0089 
0090         if(rule.action === EditActions.SetGeoBit){
0091           if(rule.geoBit !== undefined) {
0092             setGeoBit(node.fVolume, rule.geoBit, 1);
0093           }
0094         }
0095         if(rule.action === EditActions.UnsetGeoBit){
0096           if(rule.geoBit !== undefined) {
0097             setGeoBit(node.fVolume, rule.geoBit, 0);
0098           }
0099         }
0100         if(rule.action === EditActions.ToggleGeoBit){
0101           if(rule.geoBit !== undefined) {
0102             toggleGeoBit(node.fVolume, rule.geoBit);
0103           }
0104         }
0105       }
0106     }
0107     return true;  // Just continue
0108   };
0109 
0110   // Use walkGeoNodes with the collecting callback and the pattern
0111   walkGeoNodes(topNode, collectNodes, maxLevel);
0112 
0113   // Now we process nodes that we can't process on fly
0114   for(let item of postponedProcessing) {
0115     let node = item.node;
0116     let fullPath = node.fullPath;
0117     let rule:GeoNodeEditRule = item.rule;
0118     let motherVolume = item.node.fMother
0119     let siblings = motherVolume?.fNodes?.arr
0120 
0121     // Remove siblings but keep this one
0122     if(rule.action == EditActions.RemoveSiblings) {
0123       if (siblings) {
0124         motherVolume.fNodes.arr = [node]
0125       }
0126       else
0127       {
0128         console.log(`Can't get an array for: ${node} at ${fullPath}`);
0129       }
0130     }
0131 
0132     // Remove daughters by sublevels
0133     if(rule.action == EditActions.RemoveBySubLevel) {
0134       let pruneSubNodes = getGeoNodesByLevel(node, rule.pruneSubLevel);
0135       for (const pruneSubNodeItem of pruneSubNodes) {
0136         removeGeoNode(pruneSubNodeItem.geoNode);
0137       }
0138     }
0139   }
0140 
0141   return postponedProcessing;
0142 }
0143 
0144 
0145 /**
0146  * Removes a node from its mother volume.
0147  *
0148  * @param {any} node - The node to be removed.
0149  */
0150 export function removeGeoNode(node: any): void {
0151   let motherVolume = node.fMother
0152   let siblings = motherVolume?.fNodes?.arr
0153   if (siblings) {
0154     const index = siblings.indexOf(node);
0155     if (index !== -1) { // Check if the item was found
0156       siblings.splice(index, 1); // Remove the item
0157     } else {
0158       console.warn(`Item ${node} not found in array???`);
0159     }
0160   } else {
0161     console.warn(`Can't get siblings of ${node}`);
0162   }
0163 }
0164 
0165 /**
0166  * Removes all child nodes from the given node.
0167  *
0168  * @param {any} node - The node from which to remove the child nodes.
0169  */
0170 export function removeChildren(node: any): void {
0171   let daughters = node.fVolume?.fNodes?.arr;
0172 
0173   if (daughters) {
0174     node.fVolume.fNodes.arr = []
0175   } else {
0176     console.log(`Can't get child nodes of ${node}`);
0177   }
0178 }