Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-17 09:50:39

0001 // Author: Sergey Linev, 14.12.2018
0002 
0003 /*************************************************************************
0004  * Copyright (C) 1995-2023, Rene Brun and Fons Rademakers.               *
0005  * All rights reserved.                                                  *
0006  *                                                                       *
0007  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0008  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0009  *************************************************************************/
0010 
0011 #ifndef ROOT7_RGeomData
0012 #define ROOT7_RGeomData
0013 
0014 #include <vector>
0015 #include <string>
0016 #include <functional>
0017 #include <memory>
0018 
0019 #include <ROOT/Browsable/RItem.hxx>
0020 
0021 #include "TVirtualMutex.h"
0022 
0023 class TGeoNode;
0024 class TGeoManager;
0025 class TGeoShape;
0026 class TGeoMatrix;
0027 class TGeoVolume;
0028 
0029 // do not use namespace to avoid too long JSON
0030 
0031 namespace ROOT {
0032 
0033 class RGeomBrowserIter;
0034 class RLogChannel;
0035 
0036 /// Log channel for Geomviewer diagnostics.
0037 RLogChannel &RGeomLog();
0038 
0039 /** Base description of geometry node, required only to build hierarchy */
0040 
0041 class RGeomNodeBase {
0042 public:
0043    int id{0};               ///< node id, index in array
0044    std::string name;        ///< node name
0045    std::vector<int> chlds;  ///< list of childs id
0046    int vis{0};              ///< visibility flag, 0 - off, 1 - only when level==0, 99 - always
0047    bool nochlds{false};     ///< how far in hierarchy depth should be scanned
0048 
0049    std::string color;       ///< rgb code in hex format
0050    std::string material;    ///< name of the material
0051    int sortid{0};           ///<! place in sorted array, to check cuts, or id of original node when used search structures
0052 
0053    RGeomNodeBase(int _id = 0) : id(_id) {}
0054 
0055    bool IsVisible() const { return vis > 0; }
0056 
0057    /** Returns argument for regexp */
0058    const char *GetArg(int kind)
0059    {
0060       if (kind == 1) return color.c_str();
0061       if (kind == 2) return material.c_str();
0062       return name.c_str();
0063    }
0064 };
0065 
0066 /** Full node description including matrices and other attributes */
0067 
0068 class RGeomNode : public RGeomNodeBase  {
0069 public:
0070    std::vector<float> matr; ///< matrix for the node, can have reduced number of elements
0071    double vol{0};           ///<! volume estimation
0072    int nfaces{0};           ///<! number of shape faces
0073    int idshift{-1};         ///<! used to jump over then scan all geom hierarchy
0074    bool useflag{false};     ///<! extra flag, used for selection
0075    float opacity{1.};       ///<! opacity of the color
0076 
0077    RGeomNode(int _id = 0) : RGeomNodeBase(_id) {}
0078 
0079    /** True when there is shape and it can be displayed */
0080    bool CanDisplay() const { return (vol > 0.) && (nfaces > 0); }
0081 };
0082 
0083 /** \class RGeoItem
0084 \ingroup rbrowser
0085 \brief Representation of single item in the geometry browser
0086 */
0087 
0088 class RGeoItem : public Browsable::RItem {
0089 
0090 protected:
0091    // this is part for browser, visible for I/O
0092    int id{0};              ///< node id
0093    std::string color;      ///< color
0094    std::string material;   ///< material
0095    int vis{0};             ///< visibility of logical node
0096    int pvis{0};            ///< visibility of physical node
0097    bool top{false};        ///< indicates if node selected as top
0098 
0099 public:
0100 
0101    /** Default constructor */
0102    RGeoItem() = default;
0103 
0104    RGeoItem(const std::string &_name, int _nchilds, int _nodeid, const std::string &_color,
0105          const std::string &_material = "", int _vis = 0, int _pvis = 0) :
0106          Browsable::RItem(_name, _nchilds), id(_nodeid), color(_color), material(_material), vis(_vis), pvis(_pvis) {
0107    }
0108 
0109    // should be here, one needs virtual table for correct streaming of RRootBrowserReply
0110    ~RGeoItem() override = default;
0111 
0112    void SetLogicalVisibility(int logicalVis) { vis = logicalVis; }
0113    void SetPhysicalVisibility(int physicalVis) { pvis = physicalVis; }
0114    void SetTop(bool on = true) { top = on; }
0115 };
0116 
0117 
0118 /** Base class for render info block */
0119 class RGeomRenderInfo {
0120 public:
0121    /// virtual destructor required for the I/O
0122    virtual ~RGeomRenderInfo() = default;
0123 };
0124 
0125 /** Render info with raw data */
0126 class RGeomRawRenderInfo : public RGeomRenderInfo  {
0127 public:
0128    std::vector<unsigned char> raw;  ///< float vertices as raw data, JSON_base64
0129    std::vector<int> idx;            ///< vertex indexes, always triangles
0130    ~RGeomRawRenderInfo() override = default;
0131 };
0132 
0133 /** Render info with shape itself - client can produce shape better */
0134 class RGeomShapeRenderInfo : public RGeomRenderInfo  {
0135 public:
0136    TGeoShape *shape{nullptr}; ///< original shape - can be much less than binary data
0137    ~RGeomShapeRenderInfo() override = default;
0138 };
0139 
0140 
0141 /** RGeomVisible contains description of visible node
0142  * It is path to the node plus reference to shape rendering data */
0143 
0144 class RGeomVisible {
0145 public:
0146    int nodeid{0};                    ///< selected node id,
0147    int seqid{0};                     ///< sequence id, used for merging later
0148    std::vector<int> stack;           ///< path to the node, index in list of childs
0149    std::string color;                ///< color in rgb format
0150    double opacity{1};                ///< opacity
0151    RGeomRenderInfo *ri{nullptr};     ///< render information for the shape, can be same for different nodes
0152 
0153    RGeomVisible() = default;
0154    RGeomVisible(int _nodeid, int _seqid, const std::vector<int> &_stack) : nodeid(_nodeid), seqid(_seqid), stack(_stack) {}
0155 };
0156 
0157 
0158 /** Configuration parameters which can be configured on the client
0159  * Send as is to-from client */
0160 
0161 class RGeomConfig {
0162 public:
0163    int vislevel{0};                         ///< visible level
0164    int maxnumnodes{0};                      ///< maximal number of nodes
0165    int maxnumfaces{0};                      ///< maximal number of faces
0166    bool showtop{false};                     ///< show geometry top volume, off by default
0167    int build_shapes{1};                     ///< when shapes build on server  0 - never, 1 - TGeoComposite, 2 - plus non-cylindrical, 3 - all
0168    int nsegm{0};                            ///< number of segments for cylindrical shapes
0169    std::string drawopt;                     ///< draw options for TGeoPainter
0170 };
0171 
0172 
0173 /** Object with full description for drawing geometry
0174  * It includes list of visible items and list of nodes required to build them */
0175 
0176 class RGeomDrawing {
0177 public:
0178    RGeomConfig *cfg{nullptr};            ///< current configurations
0179    int numnodes{0};                      ///< total number of nodes in description
0180    std::vector<RGeomNode*> nodes;        ///< all used nodes to display visible items and not known for client
0181    std::vector<RGeomVisible> visibles;   ///< all visible items
0182 };
0183 
0184 
0185 /** Node information including rendering data */
0186 class RGeomNodeInfo {
0187 public:
0188    std::vector<std::string> path;  ///< full path to node
0189    std::string node_type;  ///< node class name
0190    std::string node_name;  ///< node name
0191    std::string shape_type; ///< shape type (if any)
0192    std::string shape_name; ///< shape class name (if any)
0193 
0194    RGeomRenderInfo *ri{nullptr};  ///< rendering information (if applicable)
0195 };
0196 
0197 /** Custom settings for physical Node visibility */
0198 class RGeomNodeVisibility {
0199 public:
0200    std::vector<int> stack;        ///< path to the node
0201    bool visible{false};           ///< visible flag
0202    RGeomNodeVisibility(const std::vector<int> &_stack, bool _visible) : stack(_stack), visible(_visible) {}
0203 };
0204 
0205 using RGeomScanFunc_t = std::function<bool(RGeomNode &, std::vector<int> &, bool, int)>;
0206 
0207 using RGeomSignalFunc_t = std::function<void(const std::string &)>;
0208 
0209 class RGeomDescription {
0210 
0211    friend class RGeomBrowserIter;
0212 
0213    class ShapeDescr {
0214    public:
0215       int id{0};                                   ///<! sequential id
0216       TGeoShape *fShape{nullptr};                  ///<! original shape
0217       int nfaces{0};                               ///<! number of faces in render data
0218       RGeomRawRenderInfo fRawInfo;                 ///<! raw render info
0219       RGeomShapeRenderInfo fShapeInfo;             ///<! shape itself as info
0220       ShapeDescr(TGeoShape *s) : fShape(s) {}
0221 
0222       bool has_shape() const { return nfaces == 1; }
0223       bool has_raw() const { return nfaces > 1; }
0224 
0225       /// Provide render info for visible item
0226       RGeomRenderInfo *rndr_info()
0227       {
0228          if (has_shape()) return &fShapeInfo;
0229          if (has_raw()) return &fRawInfo;
0230          return nullptr;
0231       }
0232 
0233       void reset()
0234       {
0235          nfaces = 0;
0236          fShapeInfo.shape = nullptr;
0237          fRawInfo.raw.clear();
0238       }
0239    };
0240 
0241    std::vector<TGeoNode *> fNodes;  ///<! flat list of all nodes
0242    std::vector<RGeomNode> fDesc;    ///<! converted description, send to client
0243    std::vector<RGeomNodeVisibility> fVisibility; ///<! custom visibility flags for physical nodes
0244 
0245    TGeoVolume *fDrawVolume{nullptr};///<! select volume independent from TGeoManager
0246    std::vector<int> fSelectedStack; ///<! selected branch of geometry by stack
0247 
0248    std::vector<int> fHighlightedStack; ///<! highlighted element by stack
0249    std::vector<int> fClickedStack;     ///<! clicked element by stack
0250 
0251    std::vector<int> fSortMap;       ///<! nodes in order large -> smaller volume
0252    std::vector<ShapeDescr> fShapes; ///<! shapes with created descriptions
0253 
0254    std::string fSearch;             ///<! search string in hierarchy
0255    std::string fSearchJson;         ///<! drawing json for search
0256    std::string fDrawJson;           ///<! JSON with main nodes drawn by client
0257    int fDrawIdCut{0};               ///<! sortid used for selection of most-significant nodes
0258    int fActualLevel{0};             ///<! level can be reduced when selecting nodes
0259    bool fPreferredOffline{false};   ///<! indicates that full description should be provided to client
0260    int fJsonComp{0};                ///<! default JSON compression
0261    std::string fActiveItemName;     ///<! name of item which should be activated in hierarchy
0262 
0263    RGeomConfig fCfg;                ///<! configuration parameter editable from GUI
0264 
0265    TVirtualMutex *fMutex{nullptr};  ///<! external mutex used to protect all data
0266 
0267    std::vector<std::pair<const void *, RGeomSignalFunc_t>> fSignals; ///<! registered signals
0268 
0269    void PackMatrix(std::vector<float> &arr, TGeoMatrix *matr);
0270 
0271    int MarkVisible(bool on_screen = false);
0272 
0273    void ProduceIdShifts();
0274 
0275    int ScanNodes(bool only_visible, int maxlvl, RGeomScanFunc_t func);
0276 
0277    void ResetRndrInfos();
0278 
0279    ShapeDescr &FindShapeDescr(TGeoShape *shape);
0280 
0281    ShapeDescr &MakeShapeDescr(TGeoShape *shape);
0282 
0283    int GetUsedNSegments(int min = 20);
0284 
0285    int CountShapeFaces(TGeoShape *shape);
0286 
0287    void CopyMaterialProperties(TGeoVolume *vol, RGeomNode &node);
0288 
0289    void CollectNodes(RGeomDrawing &drawing, bool all_nodes = false);
0290 
0291    std::string MakeDrawingJson(RGeomDrawing &drawing, bool has_shapes = false);
0292 
0293    void ClearDescription();
0294 
0295    void BuildDescription(TGeoNode *topnode, TGeoVolume *topvolume);
0296 
0297    TGeoVolume *GetVolume(int nodeid);
0298 
0299    int IsPhysNodeVisible(const std::vector<int> &stack);
0300 
0301    virtual bool IsFullModelStreamedAtOnce() const;
0302 
0303    virtual void RefineGeoItem(RGeoItem &item, const std::vector<int> &stack);
0304 
0305    /** clear drawing data without locking mutex */
0306    void _ClearDrawData()
0307    {
0308       fDrawJson.clear();
0309       fSearchJson.clear();
0310    }
0311 
0312 public:
0313    RGeomDescription() = default;
0314    virtual ~RGeomDescription() = default;
0315 
0316    void AddSignalHandler(const void *handler, RGeomSignalFunc_t func);
0317 
0318    void RemoveSignalHandler(const void *handler);
0319 
0320    void IssueSignal(const void *handler, const std::string &kind);
0321 
0322    /** Set mutex, it must be recursive one */
0323    void SetMutex(TVirtualMutex *mutex) { fMutex = mutex; }
0324    /** Return currently used mutex */
0325    TVirtualMutex *GetMutex() const { return fMutex; }
0326 
0327    /** Set maximal number of nodes which should be selected for drawing */
0328    void SetMaxVisNodes(int cnt)
0329    {
0330       TLockGuard lock(fMutex);
0331       fCfg.maxnumnodes = cnt;
0332       _ClearDrawData();
0333    }
0334    /** Returns maximal visible number of nodes, ignored when non-positive */
0335    int GetMaxVisNodes() const
0336    {
0337       TLockGuard lock(fMutex);
0338       return fCfg.maxnumnodes;
0339    }
0340 
0341    /** Set maximal number of faces which should be selected for drawing */
0342    void SetMaxVisFaces(int cnt)
0343    {
0344       TLockGuard lock(fMutex);
0345       fCfg.maxnumfaces = cnt;
0346       _ClearDrawData();
0347    }
0348    /** Returns maximal visible number of faces, ignored when non-positive */
0349    int GetMaxVisFaces() const
0350    {
0351       TLockGuard lock(fMutex);
0352       return fCfg.maxnumfaces;
0353    }
0354 
0355    /** Set maximal visible level */
0356    void SetVisLevel(int lvl = 3)
0357    {
0358       TLockGuard lock(fMutex);
0359       fCfg.vislevel = lvl;
0360       _ClearDrawData();
0361    }
0362    /** Returns maximal visible level */
0363    int GetVisLevel() const
0364    {
0365       TLockGuard lock(fMutex);
0366       return fCfg.vislevel;
0367    }
0368 
0369    /** Set draw options as string for JSROOT TGeoPainter */
0370    void SetTopVisible(bool on = true)
0371    {
0372       TLockGuard lock(fMutex);
0373       fCfg.showtop = on;
0374       _ClearDrawData();
0375    }
0376    /** Returns draw options, used for JSROOT TGeoPainter */
0377    bool GetTopVisible() const
0378    {
0379       TLockGuard lock(fMutex);
0380       return fCfg.showtop;
0381    }
0382 
0383    /** Instruct to build binary 3D model already on the server (true) or send TGeoShape as is to client, which can build model itself */
0384    void SetBuildShapes(int lvl = 1)
0385    {
0386       TLockGuard lock(fMutex);
0387       fCfg.build_shapes = lvl;
0388       _ClearDrawData();
0389    }
0390    /** Returns true if binary 3D model build already by C++ server (default) */
0391    int IsBuildShapes() const
0392    {
0393       TLockGuard lock(fMutex);
0394       return fCfg.build_shapes;
0395    }
0396 
0397    /** Set number of segments for cylindrical shapes, if 0 - default value will be used */
0398    void SetNSegments(int n = 0)
0399    {
0400       TLockGuard lock(fMutex);
0401       fCfg.nsegm = n;
0402       _ClearDrawData();
0403    }
0404    /** Return of segments for cylindrical shapes, if 0 - default value will be used */
0405    int GetNSegments() const
0406    {
0407       TLockGuard lock(fMutex);
0408       return fCfg.nsegm;
0409    }
0410 
0411    /** Set draw options as string for JSROOT TGeoPainter */
0412    void SetDrawOptions(const std::string &opt = "")
0413    {
0414       TLockGuard lock(fMutex);
0415       fCfg.drawopt = opt;
0416       _ClearDrawData();
0417    }
0418    /** Returns draw options, used for JSROOT TGeoPainter */
0419    std::string GetDrawOptions() const
0420    {
0421       TLockGuard lock(fMutex);
0422       return fCfg.drawopt;
0423    }
0424 
0425    /** Set JSON compression level for data transfer */
0426    void SetJsonComp(int comp = 0)
0427    {
0428       TLockGuard lock(fMutex);
0429       fJsonComp = comp;
0430       _ClearDrawData();
0431    }
0432    /** Returns JSON compression level for data transfer */
0433    int GetJsonComp() const
0434    {
0435       TLockGuard lock(fMutex);
0436       return fJsonComp;
0437    }
0438 
0439    /** Set preference of offline operations.
0440     * Server provides more info to client from the begin on to avoid communication */
0441    void SetPreferredOffline(bool on)
0442    {
0443       TLockGuard lock(fMutex);
0444       fPreferredOffline = on;
0445    }
0446    /** Is offline operations preferred.
0447     * After get full description, client can do most operations without extra requests */
0448    bool IsPreferredOffline() const
0449    {
0450       TLockGuard lock(fMutex);
0451       return fPreferredOffline;
0452    }
0453 
0454    /** Get top node path */
0455    const std::vector<int>& GetSelectedStack() const { return fSelectedStack; }
0456 
0457    void Build(TGeoManager *mgr, const std::string &volname = "");
0458 
0459    void Build(TGeoVolume *vol);
0460 
0461    /** Number of unique nodes in the geometry */
0462    int GetNumNodes() const { TLockGuard lock(fMutex); return fDesc.size(); }
0463 
0464    bool IsBuild() const { return GetNumNodes() > 0; }
0465 
0466    std::string ProduceJson(bool all_nodes = false);
0467 
0468    bool IsPrincipalEndNode(int nodeid);
0469 
0470    std::string ProcessBrowserRequest(const std::string &req = "");
0471 
0472    bool HasDrawData() const;
0473    void ProduceDrawData();
0474    void ProduceSearchData();
0475    std::string GetDrawJson() const { TLockGuard lock(fMutex); return fDrawJson; }
0476    std::string GetSearch() const { TLockGuard lock(fMutex); return fSearch; }
0477    std::string GetSearchJson() const { TLockGuard lock(fMutex); return fSearchJson; }
0478    void ClearDrawData();
0479 
0480    void ClearCache();
0481 
0482    int SearchVisibles(const std::string &find, std::string &hjson, std::string &json);
0483 
0484    int FindNodeId(const std::vector<int> &stack);
0485 
0486    std::string ProduceModifyReply(int nodeid);
0487 
0488    std::vector<int> MakeStackByIds(const std::vector<int> &ids);
0489 
0490    std::vector<int> MakeIdsByStack(const std::vector<int> &stack);
0491 
0492    std::vector<int> MakeStackByPath(const std::vector<std::string> &path);
0493 
0494    std::vector<std::string> MakePathByStack(const std::vector<int> &stack);
0495 
0496    bool ProduceDrawingFor(int nodeid, std::string &json, bool check_volume = false);
0497 
0498    bool SetHighlightedItem(const std::vector<int> &stack)
0499    {
0500       TLockGuard lock(fMutex);
0501       bool changed = fHighlightedStack != stack;
0502       fHighlightedStack = stack;
0503       return changed;
0504    }
0505 
0506    std::vector<int> GetHighlightedItem() const
0507    {
0508       TLockGuard lock(fMutex);
0509       return fHighlightedStack;
0510    }
0511 
0512    bool SetClickedItem(const std::vector<int> &stack)
0513    {
0514       TLockGuard lock(fMutex);
0515       bool changed = fClickedStack != stack;
0516       fClickedStack = stack;
0517       return changed;
0518    }
0519 
0520    std::vector<int> GetClickedItem() const
0521    {
0522       TLockGuard lock(fMutex);
0523       return fClickedStack;
0524    }
0525 
0526    bool SetActiveItem(const std::string &itemname)
0527    {
0528       TLockGuard lock(fMutex);
0529       bool changed = (fActiveItemName != itemname);
0530       fActiveItemName = itemname;
0531       return changed;
0532    }
0533 
0534    std::string GetActiveItem() const
0535    {
0536       TLockGuard lock(fMutex);
0537       return fActiveItemName;
0538    }
0539 
0540    bool ChangeConfiguration(const std::string &json);
0541 
0542    std::unique_ptr<RGeomNodeInfo> MakeNodeInfo(const std::vector<int> &stack);
0543 
0544    bool ChangeNodeVisibility(const std::vector<std::string> &path, bool on);
0545 
0546    bool SelectTop(const std::vector<std::string> &path);
0547 
0548    bool SetPhysNodeVisibility(const std::vector<std::string> &path, bool on = true);
0549 
0550    bool SetPhysNodeVisibility(const std::string &path, bool on = true);
0551 
0552    bool ClearPhysNodeVisibility(const std::vector<std::string> &path);
0553 
0554    bool ClearAllPhysVisibility();
0555 
0556    bool SetSearch(const std::string &query, const std::string &json);
0557 
0558    void SavePrimitive(std::ostream &fs, const std::string &name);
0559 };
0560 
0561 } // namespace ROOT
0562 
0563 #endif