Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:32:09

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 SetTop(bool on = true) { top = on; }
0113 };
0114 
0115 
0116 /** Base class for render info block */
0117 class RGeomRenderInfo {
0118 public:
0119    /// virtual destructor required for the I/O
0120    virtual ~RGeomRenderInfo() = default;
0121 };
0122 
0123 /** Render info with raw data */
0124 class RGeomRawRenderInfo : public RGeomRenderInfo  {
0125 public:
0126    std::vector<unsigned char> raw;  ///< float vertices as raw data, JSON_base64
0127    std::vector<int> idx;            ///< vertex indexes, always triangles
0128    ~RGeomRawRenderInfo() override = default;
0129 };
0130 
0131 /** Render info with shape itself - client can produce shape better */
0132 class RGeomShapeRenderInfo : public RGeomRenderInfo  {
0133 public:
0134    TGeoShape *shape{nullptr}; ///< original shape - can be much less than binary data
0135    ~RGeomShapeRenderInfo() override = default;
0136 };
0137 
0138 
0139 /** RGeomVisible contains description of visible node
0140  * It is path to the node plus reference to shape rendering data */
0141 
0142 class RGeomVisible {
0143 public:
0144    int nodeid{0};                    ///< selected node id,
0145    int seqid{0};                     ///< sequence id, used for merging later
0146    std::vector<int> stack;           ///< path to the node, index in list of childs
0147    std::string color;                ///< color in rgb format
0148    double opacity{1};                ///< opacity
0149    RGeomRenderInfo *ri{nullptr};     ///< render information for the shape, can be same for different nodes
0150 
0151    RGeomVisible() = default;
0152    RGeomVisible(int _nodeid, int _seqid, const std::vector<int> &_stack) : nodeid(_nodeid), seqid(_seqid), stack(_stack) {}
0153 };
0154 
0155 
0156 /** Configuration parameters which can be configured on the client
0157  * Send as is to-from client */
0158 
0159 class RGeomConfig {
0160 public:
0161    int vislevel{0};                         ///< visible level
0162    int maxnumnodes{0};                      ///< maximal number of nodes
0163    int maxnumfaces{0};                      ///< maximal number of faces
0164    bool showtop{false};                     ///< show geometry top volume, off by default
0165    int build_shapes{1};                     ///< when shapes build on server  0 - never, 1 - TGeoComposite, 2 - plus non-cylindrical, 3 - all
0166    int nsegm{0};                            ///< number of segments for cylindrical shapes
0167    std::string drawopt;                     ///< draw options for TGeoPainter
0168 };
0169 
0170 
0171 /** Object with full description for drawing geometry
0172  * It includes list of visible items and list of nodes required to build them */
0173 
0174 class RGeomDrawing {
0175 public:
0176    RGeomConfig *cfg{nullptr};            ///< current configurations
0177    int numnodes{0};                      ///< total number of nodes in description
0178    std::vector<RGeomNode*> nodes;        ///< all used nodes to display visible items and not known for client
0179    std::vector<RGeomVisible> visibles;   ///< all visible items
0180 };
0181 
0182 
0183 /** Node information including rendering data */
0184 class RGeomNodeInfo {
0185 public:
0186    std::vector<std::string> path;  ///< full path to node
0187    std::string node_type;  ///< node class name
0188    std::string node_name;  ///< node name
0189    std::string shape_type; ///< shape type (if any)
0190    std::string shape_name; ///< shape class name (if any)
0191 
0192    RGeomRenderInfo *ri{nullptr};  ///< rendering information (if applicable)
0193 };
0194 
0195 /** Custom settings for physical Node visibility */
0196 class RGeomNodeVisibility {
0197 public:
0198    std::vector<int> stack;        ///< path to the node
0199    bool visible{false};           ///< visible flag
0200    RGeomNodeVisibility(const std::vector<int> &_stack, bool _visible) : stack(_stack), visible(_visible) {}
0201 };
0202 
0203 using RGeomScanFunc_t = std::function<bool(RGeomNode &, std::vector<int> &, bool, int)>;
0204 
0205 using RGeomSignalFunc_t = std::function<void(const std::string &)>;
0206 
0207 class RGeomDescription {
0208 
0209    friend class RGeomBrowserIter;
0210 
0211    class ShapeDescr {
0212    public:
0213       int id{0};                                   ///<! sequential id
0214       TGeoShape *fShape{nullptr};                  ///<! original shape
0215       int nfaces{0};                               ///<! number of faces in render data
0216       RGeomRawRenderInfo fRawInfo;                 ///<! raw render info
0217       RGeomShapeRenderInfo fShapeInfo;             ///<! shape itself as info
0218       ShapeDescr(TGeoShape *s) : fShape(s) {}
0219 
0220       bool has_shape() const { return nfaces == 1; }
0221       bool has_raw() const { return nfaces > 1; }
0222 
0223       /// Provide render info for visible item
0224       RGeomRenderInfo *rndr_info()
0225       {
0226          if (has_shape()) return &fShapeInfo;
0227          if (has_raw()) return &fRawInfo;
0228          return nullptr;
0229       }
0230 
0231       void reset()
0232       {
0233          nfaces = 0;
0234          fShapeInfo.shape = nullptr;
0235          fRawInfo.raw.clear();
0236       }
0237    };
0238 
0239    std::vector<TGeoNode *> fNodes;  ///<! flat list of all nodes
0240    std::vector<RGeomNode> fDesc;    ///<! converted description, send to client
0241    std::vector<RGeomNodeVisibility> fVisibility; ///<! custom visibility flags for physical nodes
0242 
0243    TGeoVolume *fDrawVolume{nullptr};///<! select volume independent from TGeoManager
0244    std::vector<int> fSelectedStack; ///<! selected branch of geometry by stack
0245 
0246    std::vector<int> fHighlightedStack; ///<! highlighted element by stack
0247    std::vector<int> fClickedStack;     ///<! clicked element by stack
0248 
0249    std::vector<int> fSortMap;       ///<! nodes in order large -> smaller volume
0250    std::vector<ShapeDescr> fShapes; ///<! shapes with created descriptions
0251 
0252    std::string fSearch;             ///<! search string in hierarchy
0253    std::string fSearchJson;         ///<! drawing json for search
0254    std::string fDrawJson;           ///<! JSON with main nodes drawn by client
0255    int fDrawIdCut{0};               ///<! sortid used for selection of most-significant nodes
0256    int fActualLevel{0};             ///<! level can be reduced when selecting nodes
0257    bool fPreferredOffline{false};   ///<! indicates that full description should be provided to client
0258    int fJsonComp{0};                ///<! default JSON compression
0259    std::string fActiveItemName;     ///<! name of item which should be activated in hierarchy
0260 
0261    RGeomConfig fCfg;                ///<! configuration parameter editable from GUI
0262 
0263    TVirtualMutex *fMutex{nullptr};  ///<! external mutex used to protect all data
0264 
0265    std::vector<std::pair<const void *, RGeomSignalFunc_t>> fSignals; ///<! registered signals
0266 
0267    void PackMatrix(std::vector<float> &arr, TGeoMatrix *matr);
0268 
0269    int MarkVisible(bool on_screen = false);
0270 
0271    void ProduceIdShifts();
0272 
0273    int ScanNodes(bool only_visible, int maxlvl, RGeomScanFunc_t func);
0274 
0275    void ResetRndrInfos();
0276 
0277    ShapeDescr &FindShapeDescr(TGeoShape *shape);
0278 
0279    ShapeDescr &MakeShapeDescr(TGeoShape *shape);
0280 
0281    int GetUsedNSegments(int min = 20);
0282 
0283    int CountShapeFaces(TGeoShape *shape);
0284 
0285    void CopyMaterialProperties(TGeoVolume *vol, RGeomNode &node);
0286 
0287    void CollectNodes(RGeomDrawing &drawing, bool all_nodes = false);
0288 
0289    std::string MakeDrawingJson(RGeomDrawing &drawing, bool has_shapes = false);
0290 
0291    void ClearDescription();
0292 
0293    void BuildDescription(TGeoNode *topnode, TGeoVolume *topvolume);
0294 
0295    TGeoVolume *GetVolume(int nodeid);
0296 
0297    int IsPhysNodeVisible(const std::vector<int> &stack);
0298 
0299    /** clear drawing data without locking mutex */
0300    void _ClearDrawData()
0301    {
0302       fDrawJson.clear();
0303       fSearchJson.clear();
0304    }
0305 
0306 public:
0307    RGeomDescription() = default;
0308 
0309    void AddSignalHandler(const void *handler, RGeomSignalFunc_t func);
0310 
0311    void RemoveSignalHandler(const void *handler);
0312 
0313    void IssueSignal(const void *handler, const std::string &kind);
0314 
0315    /** Set mutex, it must be recursive one */
0316    void SetMutex(TVirtualMutex *mutex) { fMutex = mutex; }
0317    /** Return currently used mutex */
0318    TVirtualMutex *GetMutex() const { return fMutex; }
0319 
0320    /** Set maximal number of nodes which should be selected for drawing */
0321    void SetMaxVisNodes(int cnt)
0322    {
0323       TLockGuard lock(fMutex);
0324       fCfg.maxnumnodes = cnt;
0325       _ClearDrawData();
0326    }
0327    /** Returns maximal visible number of nodes, ignored when non-positive */
0328    int GetMaxVisNodes() const
0329    {
0330       TLockGuard lock(fMutex);
0331       return fCfg.maxnumnodes;
0332    }
0333 
0334    /** Set maximal number of faces which should be selected for drawing */
0335    void SetMaxVisFaces(int cnt)
0336    {
0337       TLockGuard lock(fMutex);
0338       fCfg.maxnumfaces = cnt;
0339       _ClearDrawData();
0340    }
0341    /** Returns maximal visible number of faces, ignored when non-positive */
0342    int GetMaxVisFaces() const
0343    {
0344       TLockGuard lock(fMutex);
0345       return fCfg.maxnumfaces;
0346    }
0347 
0348    /** Set maximal visible level */
0349    void SetVisLevel(int lvl = 3)
0350    {
0351       TLockGuard lock(fMutex);
0352       fCfg.vislevel = lvl;
0353       _ClearDrawData();
0354    }
0355    /** Returns maximal visible level */
0356    int GetVisLevel() const
0357    {
0358       TLockGuard lock(fMutex);
0359       return fCfg.vislevel;
0360    }
0361 
0362    /** Set draw options as string for JSROOT TGeoPainter */
0363    void SetTopVisible(bool on = true)
0364    {
0365       TLockGuard lock(fMutex);
0366       fCfg.showtop = on;
0367       _ClearDrawData();
0368    }
0369    /** Returns draw options, used for JSROOT TGeoPainter */
0370    bool GetTopVisible() const
0371    {
0372       TLockGuard lock(fMutex);
0373       return fCfg.showtop;
0374    }
0375 
0376    /** Instruct to build binary 3D model already on the server (true) or send TGeoShape as is to client, which can build model itself */
0377    void SetBuildShapes(int lvl = 1)
0378    {
0379       TLockGuard lock(fMutex);
0380       fCfg.build_shapes = lvl;
0381       _ClearDrawData();
0382    }
0383    /** Returns true if binary 3D model build already by C++ server (default) */
0384    int IsBuildShapes() const
0385    {
0386       TLockGuard lock(fMutex);
0387       return fCfg.build_shapes;
0388    }
0389 
0390    /** Set number of segments for cylindrical shapes, if 0 - default value will be used */
0391    void SetNSegments(int n = 0)
0392    {
0393       TLockGuard lock(fMutex);
0394       fCfg.nsegm = n;
0395       _ClearDrawData();
0396    }
0397    /** Return of segments for cylindrical shapes, if 0 - default value will be used */
0398    int GetNSegments() const
0399    {
0400       TLockGuard lock(fMutex);
0401       return fCfg.nsegm;
0402    }
0403 
0404    /** Set draw options as string for JSROOT TGeoPainter */
0405    void SetDrawOptions(const std::string &opt = "")
0406    {
0407       TLockGuard lock(fMutex);
0408       fCfg.drawopt = opt;
0409       _ClearDrawData();
0410    }
0411    /** Returns draw options, used for JSROOT TGeoPainter */
0412    std::string GetDrawOptions() const
0413    {
0414       TLockGuard lock(fMutex);
0415       return fCfg.drawopt;
0416    }
0417 
0418    /** Set JSON compression level for data transfer */
0419    void SetJsonComp(int comp = 0)
0420    {
0421       TLockGuard lock(fMutex);
0422       fJsonComp = comp;
0423       _ClearDrawData();
0424    }
0425    /** Returns JSON compression level for data transfer */
0426    int GetJsonComp() const
0427    {
0428       TLockGuard lock(fMutex);
0429       return fJsonComp;
0430    }
0431 
0432    /** Set preference of offline operations.
0433     * Server provides more info to client from the begin on to avoid communication */
0434    void SetPreferredOffline(bool on)
0435    {
0436       TLockGuard lock(fMutex);
0437       fPreferredOffline = on;
0438    }
0439    /** Is offline operations preferred.
0440     * After get full description, client can do most operations without extra requests */
0441    bool IsPreferredOffline() const
0442    {
0443       TLockGuard lock(fMutex);
0444       return fPreferredOffline;
0445    }
0446 
0447    /** Get top node path */
0448    const std::vector<int>& GetSelectedStack() const { return fSelectedStack; }
0449 
0450    void Build(TGeoManager *mgr, const std::string &volname = "");
0451 
0452    void Build(TGeoVolume *vol);
0453 
0454    /** Number of unique nodes in the geometry */
0455    int GetNumNodes() const { TLockGuard lock(fMutex); return fDesc.size(); }
0456 
0457    bool IsBuild() const { return GetNumNodes() > 0; }
0458 
0459    std::string ProduceJson(bool all_nodes = false);
0460 
0461    bool IsPrincipalEndNode(int nodeid);
0462 
0463    std::string ProcessBrowserRequest(const std::string &req = "");
0464 
0465    bool HasDrawData() const;
0466    void ProduceDrawData();
0467    void ProduceSearchData();
0468    std::string GetDrawJson() const { TLockGuard lock(fMutex); return fDrawJson; }
0469    std::string GetSearch() const { TLockGuard lock(fMutex); return fSearch; }
0470    std::string GetSearchJson() const { TLockGuard lock(fMutex); return fSearchJson; }
0471    void ClearDrawData();
0472 
0473    void ClearCache();
0474 
0475    int SearchVisibles(const std::string &find, std::string &hjson, std::string &json);
0476 
0477    int FindNodeId(const std::vector<int> &stack);
0478 
0479    std::string ProduceModifyReply(int nodeid);
0480 
0481    std::vector<int> MakeStackByIds(const std::vector<int> &ids);
0482 
0483    std::vector<int> MakeIdsByStack(const std::vector<int> &stack);
0484 
0485    std::vector<int> MakeStackByPath(const std::vector<std::string> &path);
0486 
0487    std::vector<std::string> MakePathByStack(const std::vector<int> &stack);
0488 
0489    bool ProduceDrawingFor(int nodeid, std::string &json, bool check_volume = false);
0490 
0491    bool SetHighlightedItem(const std::vector<int> &stack)
0492    {
0493       TLockGuard lock(fMutex);
0494       bool changed = fHighlightedStack != stack;
0495       fHighlightedStack = stack;
0496       return changed;
0497    }
0498 
0499    std::vector<int> GetHighlightedItem() const
0500    {
0501       TLockGuard lock(fMutex);
0502       return fHighlightedStack;
0503    }
0504 
0505    bool SetClickedItem(const std::vector<int> &stack)
0506    {
0507       TLockGuard lock(fMutex);
0508       bool changed = fClickedStack != stack;
0509       fClickedStack = stack;
0510       return changed;
0511    }
0512 
0513    std::vector<int> GetClickedItem() const
0514    {
0515       TLockGuard lock(fMutex);
0516       return fClickedStack;
0517    }
0518 
0519    bool SetActiveItem(const std::string &itemname)
0520    {
0521       TLockGuard lock(fMutex);
0522       bool changed = (fActiveItemName != itemname);
0523       fActiveItemName = itemname;
0524       return changed;
0525    }
0526 
0527    std::string GetActiveItem() const
0528    {
0529       TLockGuard lock(fMutex);
0530       return fActiveItemName;
0531    }
0532 
0533    bool ChangeConfiguration(const std::string &json);
0534 
0535    std::unique_ptr<RGeomNodeInfo> MakeNodeInfo(const std::vector<int> &stack);
0536 
0537    bool ChangeNodeVisibility(const std::vector<std::string> &path, bool on);
0538 
0539    bool SelectTop(const std::vector<std::string> &path);
0540 
0541    bool SetPhysNodeVisibility(const std::vector<std::string> &path, bool on = true);
0542 
0543    bool SetPhysNodeVisibility(const std::string &path, bool on = true);
0544 
0545    bool ClearPhysNodeVisibility(const std::vector<std::string> &path);
0546 
0547    bool ClearAllPhysVisibility();
0548 
0549    bool SetSearch(const std::string &query, const std::string &json);
0550 
0551    void SavePrimitive(std::ostream &fs, const std::string &name);
0552 };
0553 
0554 } // namespace ROOT
0555 
0556 #endif