graph.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. //
  2. //
  3. //////////////////////////////////////////////////////////////////////////////
  4. //
  5. // Copyright 2015 Autodesk, Inc. All rights reserved.
  6. //
  7. // Use of this software is subject to the terms of the Autodesk license
  8. // agreement provided at the time of installation or download, or which
  9. // otherwise accompanies this software in either electronic or hard copy form.
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. //
  13. // ========= graph.h: AcDbGraph classes ================
  14. //
  15. // This header defines classes:
  16. //
  17. // AcDbGraph - a generic graph container class
  18. // AcDbGraphNode - the nodes for the graph container
  19. // AcDbGraphStack - stack for graph nodes
  20. //
  21. // Detection for circular references is done by internally creating
  22. // a duplicate set of references in each node and then triming away
  23. // all leaf nodes, which terminate without circularity. If any nodes
  24. // remain in the duplicate graph, those nodes exist in a cycle.
  25. // AcDbGraph::findCycles() is used to set up the internal cycle
  26. // information and enable several query methods to return information
  27. // about any cycles found.
  28. #ifndef AD_GRAPH_H
  29. #define AD_GRAPH_H 1
  30. #include "dbmain.h"
  31. #pragma pack (push, 8)
  32. class AcDbGraph;
  33. // =====================================
  34. // Generic Graph Classes
  35. // =====================================
  36. class AcDbGraphNode : public AcHeapOperators
  37. {
  38. friend class AcDbGraph;
  39. public:
  40. AcDbGraphNode(void* pData = NULL);
  41. virtual ~AcDbGraphNode();
  42. // Enum values used to mark nodes using markAs(), etc.
  43. //
  44. enum Flags { kNone = 0x00,
  45. kVisited = 0x01, // Cycle: detection
  46. kOutsideRefed = 0x02, // List: cannot Detach
  47. kSelected = 0x04, // List: user's selection
  48. kInList = 0x08, // List: is on it
  49. kListAll = 0x0E, // List: for clear all
  50. kFirstLevel = 0x10, // has edge from root
  51. kUnresTree = 0x20, // In an Unresolved tree
  52. kAll = 0x2F }; // Note, this does
  53. // not clear kFirstLevel,
  54. // which is read-only
  55. void* data () const;
  56. void setData (void*);
  57. int numOut () const;
  58. int numIn () const;
  59. AcDbGraphNode* in (int) const;
  60. AcDbGraphNode* out (int) const;
  61. Acad::ErrorStatus addRefTo (AcDbGraphNode*);
  62. Acad::ErrorStatus removeRefTo (AcDbGraphNode*);
  63. Acad::ErrorStatus disconnectAll ();
  64. AcDbGraph* owner () const;
  65. bool isMarkedAs (Adesk::UInt8 flags) const;
  66. Acad::ErrorStatus markAs (Adesk::UInt8 flags);
  67. Acad::ErrorStatus clear (Adesk::UInt8 flags);
  68. Acad::ErrorStatus markTree (Adesk::UInt8 flags,
  69. AcDbVoidPtrArray* = NULL);
  70. // Circularity detection methods
  71. int numCycleOut () const;
  72. int numCycleIn () const;
  73. AcDbGraphNode* cycleIn (int) const;
  74. AcDbGraphNode* cycleOut (int) const;
  75. AcDbGraphNode* nextCycleNode () const;
  76. bool isCycleNode () const;
  77. void setEdgeGrowthRate(int outEdgeRate, int inEdgeRate);
  78. private:
  79. // These are currently not supported
  80. //
  81. AcDbGraphNode(const AcDbGraphNode&);
  82. AcDbGraphNode& operator = (const AcDbGraphNode&);
  83. AcDbVoidPtrArray mOutgoing;
  84. AcDbVoidPtrArray mIncoming;
  85. void* mpData;
  86. void setFirstLevel (Adesk::Boolean);
  87. Adesk::UInt8 mFlags;
  88. // Circularity detection
  89. Acad::ErrorStatus setOwner (AcDbGraph*);
  90. Acad::ErrorStatus resetCycles ();
  91. Acad::ErrorStatus removeCycleRefTo (AcDbGraphNode*);
  92. Acad::ErrorStatus clearCycles ();
  93. AcDbGraph* mpOwner;
  94. AcDbVoidPtrArray* mpCycleOut;
  95. AcDbVoidPtrArray* mpCycleIn;
  96. };
  97. class AcDbGraph : public AcHeapOperators
  98. {
  99. friend class AcDbGraphNode;
  100. public:
  101. AcDbGraph(AcDbGraphNode* pRoot = NULL);
  102. virtual ~AcDbGraph();
  103. AcDbGraphNode* node (int index) const;
  104. AcDbGraphNode* rootNode () const;
  105. int numNodes () const;
  106. bool isEmpty () const;
  107. Acad::ErrorStatus addNode (AcDbGraphNode*);
  108. Acad::ErrorStatus addEdge (AcDbGraphNode* pFrom,
  109. AcDbGraphNode* pTo);
  110. Acad::ErrorStatus delNode (AcDbGraphNode*);
  111. void reset ();
  112. void clearAll (Adesk::UInt8 flags);
  113. void getOutgoing (AcDbVoidPtrArray&);
  114. // Cycle detection
  115. virtual Adesk::Boolean findCycles (AcDbGraphNode* pStart = NULL);
  116. Acad::ErrorStatus breakCycleEdge (AcDbGraphNode* pFrom,
  117. AcDbGraphNode* pTo);
  118. void setNodeGrowthRate(int rate);
  119. protected:
  120. Acad::ErrorStatus clearAllCycles ();
  121. private:
  122. // These are currently not supported
  123. //
  124. AcDbGraph(const AcDbGraph&);
  125. AcDbGraph& operator = (const AcDbGraph&);
  126. AcDbVoidPtrArray mNodes;
  127. // Cycle detection
  128. AcDbVoidPtrArray* mpCycleNodes;
  129. void setDirty ();
  130. bool mDirty;
  131. };
  132. class AcDbGraphStack : public AcHeapOperators
  133. {
  134. public:
  135. AcDbGraphStack(int initPhysicalLength = 0, int initGrowLength = 8);
  136. ~AcDbGraphStack();
  137. Acad::ErrorStatus push (AcDbGraphNode*);
  138. AcDbGraphNode* pop ();
  139. AcDbGraphNode* top () const;
  140. bool isEmpty () const;
  141. private:
  142. AcDbVoidPtrArray mStack;
  143. };
  144. // =====================================
  145. // Inline methods
  146. // =====================================
  147. // AcDbGraphNode inlines ...
  148. inline void* AcDbGraphNode::data() const { return mpData; }
  149. inline void AcDbGraphNode::setData(void* pData) { mpData = pData; }
  150. inline int AcDbGraphNode::numOut() const { return mOutgoing.length(); }
  151. inline int AcDbGraphNode::numIn() const { return mIncoming.length(); }
  152. inline AcDbGraphNode* AcDbGraphNode::in(int idx) const
  153. { return (AcDbGraphNode*)mIncoming.at(idx); }
  154. inline AcDbGraphNode* AcDbGraphNode::out(int idx) const
  155. { return (AcDbGraphNode*)mOutgoing.at(idx); }
  156. inline bool AcDbGraphNode::isMarkedAs(Adesk::UInt8 flag) const
  157. { return (this->mFlags & flag) != 0; }
  158. inline AcDbGraph* AcDbGraphNode::owner() const { return mpOwner; }
  159. inline Acad::ErrorStatus AcDbGraphNode::setOwner(AcDbGraph* pOwn)
  160. { assert(!mpOwner); if (mpOwner) return Acad::eInvalidOwnerObject;
  161. mpOwner = pOwn; return Acad::eOk; }
  162. inline int AcDbGraphNode::numCycleOut() const
  163. { return mpCycleOut == NULL ? 0 : mpCycleOut->length(); }
  164. inline int AcDbGraphNode::numCycleIn() const
  165. { return mpCycleIn == NULL ? 0 : mpCycleIn->length(); }
  166. inline AcDbGraphNode* AcDbGraphNode::cycleOut(int idx) const
  167. { return (AcDbGraphNode*)
  168. (mpCycleOut == NULL ? NULL : mpCycleOut->at(idx)); }
  169. inline AcDbGraphNode* AcDbGraphNode::cycleIn(int idx) const
  170. { return (AcDbGraphNode*)
  171. (mpCycleIn == NULL ? NULL : mpCycleIn->at(idx)); }
  172. inline AcDbGraphNode* AcDbGraphNode::nextCycleNode() const
  173. { assert(mpCycleOut != NULL); return cycleOut(0); }
  174. inline bool AcDbGraphNode::isCycleNode() const
  175. { return mpCycleIn != NULL || mpCycleOut != NULL; }
  176. // AcDbGraph inlines ...
  177. inline int AcDbGraph::numNodes() const { return mNodes.length(); }
  178. inline AcDbGraphNode* AcDbGraph::node(int idx) const
  179. { return (AcDbGraphNode*)mNodes.at(idx); }
  180. inline AcDbGraphNode* AcDbGraph::rootNode() const
  181. { return (numNodes() > 0) ? node(0) : NULL; }
  182. inline bool AcDbGraph::isEmpty() const
  183. { return numNodes() == 0; }
  184. inline void AcDbGraph::setDirty() { mDirty = true; }
  185. // XreGraphStack inlines ...
  186. inline bool AcDbGraphStack::isEmpty() const
  187. { return mStack.isEmpty(); }
  188. inline AcDbGraphNode* AcDbGraphStack::top() const
  189. { return isEmpty() ? NULL : (AcDbGraphNode*)mStack.last(); }
  190. #pragma pack (pop)
  191. #endif