graph_model.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. """Graph Model.
  2. """
  3. from enum import Enum
  4. from systemrelation import graph_model
  5. from systemrelation import systemdatautils
  6. from systemrelation import systemutils
  7. from systemrelation import revit_const
  8. class SystemVertex:
  9. """Graph Vertex.
  10. """
  11. vertex_type = 0
  12. def __init__(self,parent, connector,system_data):
  13. self.connector=connector
  14. self.system_data = system_data
  15. self.parent= parent
  16. def __str__(self):
  17. return str(systemutils.get_specify_type_parent(self,FloorGraph).model.floor_name)+':'+str(self.system_data.source_id)
  18. def __eq__(self, other):
  19. return self.system_data.source_id==other.system_data.source_id
  20. def __hash__(self):
  21. return hash(self.system_data.source_id)
  22. def is_open_vertical_pipe(self):
  23. '''
  24. Connector to other floor
  25. :return:
  26. '''
  27. if (len(self.connector.connect_id_json)==0):
  28. if( self.connector.belong_type in revit_const.MEPCURVE):
  29. return True
  30. return False
  31. class SystemEdge:
  32. """Graph Edge."""
  33. # edge data.contain all edge element
  34. flow_direction = 0
  35. def __init__(self,parent, system_data):
  36. self.system_data = system_data
  37. self.parent = parent
  38. def get_vertexs(self):
  39. return [self.start_vertex,self.end_vertex]
  40. # @property
  41. # def start_vertex(self):
  42. # return self.start_vertex
  43. #
  44. # @property
  45. # def end_vertex(self):
  46. # return self.end_vertex
  47. class SystemGraph:
  48. """System Graph
  49. """
  50. # system edge array.
  51. system_graph_id = ''
  52. # system type Name
  53. system_name = ""
  54. def __init__(self,parent):
  55. self.system_edges = []
  56. self.parent=parent
  57. def add_edge(self, c1, c2, elements):
  58. """
  59. Create edge and add to system_edges list
  60. :param c1:
  61. :param c2:
  62. :param elements:
  63. :return:
  64. """
  65. edge = SystemEdge(self,elements)
  66. edge.start_vertex = SystemVertex(edge,c1,elements[0])
  67. edge.end_vertex = SystemVertex(edge,c2,elements[-1])
  68. self.system_edges.append(edge)
  69. return edge
  70. def get_open_vertical_pipes(self):
  71. """
  72. Get all open vertical pipe Vertex
  73. :return:
  74. """
  75. open_pipes=[]
  76. for edge in self.system_edges:
  77. for vertex in edge.get_vertexs():
  78. if vertex.is_open_vertical_pipe():
  79. open_pipes.append(vertex)
  80. return open_pipes
  81. class FloorGraph:
  82. """FLoor Graph.
  83. May contain one or more SystemGraph.
  84. """
  85. def __init__(self,model, system_name, domain):
  86. self.model=model;
  87. self.system_name = system_name
  88. self.domain = domain
  89. floor_connectors = systemdatautils.get_connectors_data(self.model.file_id, system_name, domain)
  90. floor_connectors = systemutils.sort_connectors(floor_connectors)
  91. floor_connectors = list(map(systemutils.add_attr_is_used, floor_connectors))
  92. self.connector_data = (floor_connectors)
  93. self.element_data = systemutils.list_to_dict(systemdatautils.get_element_data(self.model.file_id))
  94. self.system_graphs = []
  95. def get_floor_graphs(self):
  96. """Get current floor graph.
  97. system_name,domain
  98. """
  99. for connector in self.connector_data:
  100. system_graph = graph_model.SystemGraph(self)
  101. graph_next_connectors = [connector]
  102. # dept-first
  103. for connector in graph_next_connectors:
  104. self.get_path(connector, system_graph, graph_next_connectors)
  105. if len(system_graph.system_edges) != 0:
  106. self.system_graphs.append(system_graph)
  107. print("Next loop:",connector.source_id)
  108. return self.system_graphs
  109. def get_path(self, connector, system_graph, graph_next_connectors):
  110. """
  111. Get Graph_Edge start with connector,end with triple ,cross,equipment.
  112. :param connector:
  113. :return:Graph_Edge
  114. """
  115. system_edge = None
  116. if (connector.is_used):
  117. return system_edge
  118. try:
  119. #Add other side to be spreaded
  120. graph_next_connectors.extend(self.get_other_connectors(connector))
  121. edge_elements = [self.get_element(connector.belong)]
  122. current_connector = connector
  123. while (current_connector is not None):
  124. current_connector.is_used = True
  125. connecteds = self.get_connecteds(current_connector.connect_id_json)
  126. if len(connecteds) > 1:
  127. raise Exception("connected to many.connector_id:", current_connector.connect_id_json)
  128. #Open Connector
  129. if len(connecteds) == 0:
  130. if current_connector != connector:
  131. system_edge = system_graph.add_edge(connector, current_connector, edge_elements)
  132. break
  133. next_connector = connecteds[0]
  134. if next_connector is not None and next_connector.domain == connector.domain and next_connector.mep_system_type == connector.mep_system_type:
  135. next_element = self.get_element(next_connector.belong)
  136. edge_elements.append(next_element)
  137. other_connectors = self.get_other_connectors(next_connector)
  138. if systemutils.is_break_condition(next_element) or len(other_connectors) != 1:
  139. print(next_connector.source_id)
  140. next_connector.is_used = True
  141. if(len(other_connectors) != 1):
  142. graph_next_connectors.extend(other_connectors)
  143. system_edge = system_graph.add_edge(connector, next_connector, edge_elements)
  144. break
  145. if len(other_connectors)==1:
  146. next_connector.is_used = True
  147. current_connector = other_connectors[0]
  148. continue
  149. current_connector = None
  150. except Exception as e:
  151. print(e)
  152. return system_edge
  153. def get_other_connectors(self, use_connector):
  154. """
  155. Get the connector owner other connectors.
  156. belong,domian,mep_system_type same.
  157. is_used==False.
  158. :param use_connector:
  159. :return:
  160. """
  161. connectors = [connector for connector in self.connector_data if
  162. connector != use_connector and connector.belong == use_connector.belong and connector.domain == use_connector.domain and connector.mep_system_type == use_connector.mep_system_type]
  163. connectors = [connector for connector in connectors if bool(1 - connector.is_used)]
  164. return connectors
  165. def get_connecteds(self, connetor_id):
  166. """
  167. Get Ref Connector. may have two.like system logic connector
  168. :param connetor_id:
  169. :return:
  170. """
  171. connectors = list(self.get_connector(id) for id in connetor_id)
  172. return connectors
  173. def get_connector(self, connector_id):
  174. """
  175. Get Connector by Id.
  176. :param connector_id:
  177. :return:
  178. """
  179. cons = list(c for c in self.connector_data if c.id == connector_id)
  180. return cons[0]
  181. def get_element(self, element_id):
  182. """
  183. Get Element by Id.
  184. :param eleemnt_id:
  185. :return:
  186. """
  187. return self.element_data[element_id]
  188. class GroupedSystemGraph:
  189. '''
  190. Systemgraph be connected via vertical pipe
  191. May contain more system.Different floor;
  192. '''
  193. def __init__(self, systemgraph):
  194. self.systemgraphs=[systemgraph]
  195. self.connectedges=[]
  196. def add_system(self,systemgraph):
  197. '''
  198. Add system into groupsystem
  199. :param systemgraph:
  200. :return:
  201. '''
  202. self.systemgraphs.append(systemgraph)
  203. def add_edge(self,vertex1,vertex2):
  204. '''
  205. Create virtual edge that connect two floor.
  206. Add edge to edge list.
  207. :param vertex1:
  208. :param vertex2:
  209. :return:
  210. '''
  211. edge=SystemEdge(None,None)
  212. edge.start_vertex=vertex1
  213. edge.end_vertex=vertex2
  214. self.connectedges.append(edge)
  215. class ProjectGraph:
  216. '''
  217. ProjectGraph contain more than one GroupedSystemGraph.
  218. '''
  219. def __init__(self):
  220. self.groupedsystemgraphs=[]
  221. def remove_groupedsystemgraphs(self, systemgraph):
  222. '''
  223. Check system has existed in grouped system list.
  224. if exist remove it .
  225. :param systemgraph:
  226. :return:
  227. '''
  228. try:
  229. tt = next(groupedsystemgraph for groupedsystemgraph in self.groupedsystemgraphs if
  230. systemgraph in groupedsystemgraph.systemgraphs)
  231. if tt:
  232. self.groupedsystemgraphs.remove(tt)
  233. except StopIteration:
  234. pass
  235. class SystemFlowDirection(Enum):
  236. """Edge Flow Direction.
  237. """
  238. flow_in = 1
  239. flow_out = -1
  240. flow_undefine = 0
  241. class SystemVertexType(Enum):
  242. """Vertex Type.
  243. """
  244. real_point = 0
  245. imaginary_point = 1
  246. hollow_dot = 2