Browse Source

mxg:block system in the project

mengxiangge 5 years ago
parent
commit
715d4d8c65

+ 115 - 25
systemrelation/graph_model.py

@@ -1,19 +1,51 @@
 """Graph Model.
-
 """
 from enum import Enum
 from systemrelation import graph_model
 from systemrelation import systemdatautils
 from systemrelation import systemutils
+from systemrelation import revit_const
+
+class SystemVertex:
+	"""Graph Vertex.
+	"""
+	vertex_type = 0
+
+	def __init__(self,parent, connector,system_data):
+		self.connector=connector
+		self.system_data = system_data
+		self.parent= parent
+
+	def __str__(self):
+		return str(systemutils.get_specify_type_parent(self,FloorGraph).model.floor_name)+':'+str(self.system_data.source_id)
+
+	def __eq__(self, other):
+		return self.system_data.source_id==other.system_data.source_id
 
+	def __hash__(self):
+		return hash(self.system_data.source_id)
+
+	def is_open_vertical_pipe(self):
+		'''
+		Connector to other floor
+		:return:
+		'''
+		if (len(self.connector.connect_id_json)==0):
+			if( self.connector.belong_type in revit_const.MEPCURVE):
+				return True
+		return False
 
 class SystemEdge:
 	"""Graph Edge."""
 	# edge data.contain all edge element
 	flow_direction = 0
 
-	def __init__(self, system_data):
+	def __init__(self,parent, system_data):
 		self.system_data = system_data
+		self.parent = parent
+
+	def get_vertexs(self):
+		return [self.start_vertex,self.end_vertex]
 # @property
 # def start_vertex(self):
 # 	return self.start_vertex
@@ -23,18 +55,6 @@ class SystemEdge:
 # 	return self.end_vertex
 
 
-class SystemVertex:
-	"""Graph Vertex.
-	"""
-	vertex_type = 0
-
-	def __init__(self, system_data):
-		self.system_data = system_data
-
-	def __str__(self):
-		return str(self.system_data.source_id)
-
-
 class SystemGraph:
 	"""System Graph
 	"""
@@ -43,32 +63,51 @@ class SystemGraph:
 	# system type Name
 	system_name = ""
 
-	def __init__(self):
+	def __init__(self,parent):
 		self.system_edges = []
+		self.parent=parent
 
 	def add_edge(self, c1, c2, elements):
-		edge = SystemEdge(elements)
-		edge.start_vertex = SystemVertex(elements[0])
-		edge.end_vertex = SystemVertex(elements[-1])
+		"""
+		Create edge and add to system_edges list
+		:param c1:
+		:param c2:
+		:param elements:
+		:return:
+		"""
+		edge = SystemEdge(self,elements)
+		edge.start_vertex = SystemVertex(edge,c1,elements[0])
+		edge.end_vertex = SystemVertex(edge,c2,elements[-1])
 		self.system_edges.append(edge)
 		return edge
 
+	def get_open_vertical_pipes(self):
+		"""
+		Get all open vertical pipe Vertex
+		:return:
+		"""
+		open_pipes=[]
+		for edge in self.system_edges:
+			for	vertex in edge.get_vertexs():
+				if vertex.is_open_vertical_pipe():
+					open_pipes.append(vertex)
+		return open_pipes
+
 
 class FloorGraph:
 	"""FLoor Graph.
 	May contain one or more SystemGraph.
 	"""
 
-	def __init__(self, project_id,model_id, system_name, domain):
-		self.project_id=project_id
-		self.model_id = model_id
+	def __init__(self,model, system_name, domain):
+		self.model=model;
 		self.system_name = system_name
 		self.domain = domain
-		floor_connectors = systemdatautils.get_connectors_data(model_id, system_name, domain)
+		floor_connectors = systemdatautils.get_connectors_data(self.model.file_id, system_name, domain)
 		floor_connectors = systemutils.sort_connectors(floor_connectors)
 		floor_connectors = list(map(systemutils.add_attr_is_used, floor_connectors))
 		self.connector_data = (floor_connectors)
-		self.element_data = systemutils.list_to_dict(systemdatautils.get_element_data(model_id))
+		self.element_data = systemutils.list_to_dict(systemdatautils.get_element_data(self.model.file_id))
 		self.system_graphs = []
 
 	def get_floor_graphs(self):
@@ -76,7 +115,7 @@ class FloorGraph:
 		system_name,domain
 		"""
 		for connector in self.connector_data:
-			system_graph = graph_model.SystemGraph()
+			system_graph = graph_model.SystemGraph(self)
 			graph_next_connectors = [connector]
 			# dept-first
 			for connector in graph_next_connectors:
@@ -96,7 +135,7 @@ class FloorGraph:
 		if (connector.is_used):
 			return system_edge
 		try:
-			#Add other side to be Spreaded
+			#Add other side to be spreaded
 			graph_next_connectors.extend(self.get_other_connectors(connector))
 			edge_elements = [self.get_element(connector.belong)]
 			current_connector = connector
@@ -171,6 +210,57 @@ class FloorGraph:
 		"""
 		return self.element_data[element_id]
 
+class GroupedSystemGraph:
+	'''
+	Systemgraph be connected  via vertical pipe
+	May contain more system.Different floor;
+	'''
+	def __init__(self, systemgraph):
+		self.systemgraphs=[systemgraph]
+		self.connectedges=[]
+	def add_system(self,systemgraph):
+		'''
+		Add system into groupsystem
+		:param systemgraph:
+		:return:
+		'''
+		self.systemgraphs.append(systemgraph)
+
+	def add_edge(self,vertex1,vertex2):
+		'''
+		Create virtual edge that connect two floor.
+		Add edge to edge list.
+		:param vertex1:
+		:param vertex2:
+		:return:
+		'''
+		edge=SystemEdge(None,None)
+		edge.start_vertex=vertex1
+		edge.end_vertex=vertex2
+		self.connectedges.append(edge)
+
+class ProjectGraph:
+	'''
+	ProjectGraph contain more than one GroupedSystemGraph.
+	'''
+	def __init__(self):
+		self.groupedsystemgraphs=[]
+
+	def remove_groupedsystemgraphs(self, systemgraph):
+		'''
+		Check system has existed in grouped system list.
+		if exist remove it .
+		:param systemgraph:
+		:return:
+		'''
+		try:
+			tt = next(groupedsystemgraph for groupedsystemgraph in self.groupedsystemgraphs if
+					  systemgraph in groupedsystemgraph.systemgraphs)
+			if tt:
+				self.groupedsystemgraphs.remove(tt)
+		except StopIteration:
+			pass
+
 
 class SystemFlowDirection(Enum):
 	"""Edge Flow Direction.

+ 11 - 6
systemrelation/system_test.py

@@ -1,13 +1,18 @@
 from systemrelation import graph_model
 from systemrelation import systemgraph_display
 from systemrelation import systemdatautils
+from systemrelation import systemutils
 
 if '__main__'==__name__:
-	project_id=""
-	model_id="0ebf6b7ae97211e9a27c57c0742fab4c"
+	project_id="Pj1101010015"
 	system_name="冷冻水供水管"
 	domain="DomainPiping"
-	g=graph_model.FloorGraph(project_id,model_id,system_name,domain)
-	g.get_floor_graphs()
-	systemdatautils.save_floor_graph_data(g)
-	systemgraph_display.show_floor(g)
+	models=systemdatautils.get_project_models(project_id)
+	floorgraphs=[]
+	for model in models:
+		g=graph_model.FloorGraph(model,system_name,domain)
+		g.get_floor_graphs()
+		floorgraphs.append(g)
+	projectgraph=systemutils.combine_systemgraph(floorgraphs)
+	systemdatautils.save_project_data(projectgraph,project_id)
+	systemgraph_display.show_project(projectgraph)

+ 95 - 13
systemrelation/systemdatautils.py

@@ -3,10 +3,60 @@
 """
 import test
 from systemrelation import systemutils
+from systemrelation import graph_model
 def get_dicdata(sql,dic):
+	"""
+	Request db for data through sql.
+	Convert data to dict.
+	:param sql:
+	:param dic:
+	:return:
+	"""
 	data=test.get_data(sql)
 	dic_data=[dict(zip(dic,item)) for item in data]
 	return list(dic_data)
+def get_project_models(project_id):
+	'''
+	Get all the models in the project.
+	project-->folder-->model.
+	:param project_id:
+	:return:
+	'''
+	element_data = []
+	sql ="select " \
+		"file.id as file_id" \
+		",file.original_name as file_name" \
+		",file.status as file_status" \
+		",floor.id as floor_id" \
+		",floor.floor_name as floor_name" \
+		",folder.id as folder_id" \
+		",folder.name as folder_name" \
+		",folder.project_id as project_id " \
+		"from revit.model_file as file " \
+		"inner join " \
+		"revit.model_floor as floor " \
+		"on ( file.id=floor.current_model_id) " \
+		"inner join " \
+		"revit.model_folder as folder " \
+		"on  (floor.folder_id=folder.id )" \
+		"where folder.project_id='%s'" \
+		"and folder.id='bbe510dbe26011e999b69b669ea08505'"\
+		 % (project_id)
+	#"and file.status=4 "\
+	COMPONENT_KEYS = [
+		'file_id',
+		'file_name',
+		'file_status',
+		'floor_id',
+		'floor_name',
+		'folder_id',
+		'folder_name',
+		'project_id'
+	]
+	element_data.extend(get_dicdata(sql, COMPONENT_KEYS))
+	element_data = list(map(systemutils.dic2obj, element_data))
+	return element_data
+
 def get_element_data(model_id):
 	"""
 	Cache all Element from Db
@@ -144,23 +194,55 @@ def get_connectors_data(model_id, system_name, domain):
 	connector_data.extend(get_dicdata(connector_sql, CONNECTOR_KEYS))
 	connector_data=list(map(systemutils.dic2obj,connector_data))
 	return connector_data
-def save_floor_graph_data(floor_graph):
+
+def save_project_data(project_graph,project_id):
+	"""
+	Sava project graph data.
+	:param floor_graph:
+	:return:
+	"""
+	del_project_data(project_id)
+	# Create
 	block_id=0
-	for s in floor_graph.system_graphs:
-		sava_system_graph_data(s,block_id,floor_graph.project_id)
+	for g in project_graph.groupedsystemgraphs:
+		for s in g.systemgraphs:
+			for e in s.system_edges:
+				save_edge_data(e, block_id)
+		for e in g.connectedges:
+			save_edge_data(e,block_id)
 		block_id+=1
-def sava_system_graph_data(system_graph,block_id,project_id):
-	for e in system_graph.system_edges:
-		save_connected_block(e.start_vertex.system_data,e.end_vertex.system_data,block_id,project_id)
-def save_connected_block(vertex1,vertex2,block_id,project_id):
+def save_edge_data(edge,block_id):
+	"""
+	Save edge info using sql
+	:param edge:
+	:param block_id:
+	:return:
+	"""
+	vertex1=edge.start_vertex
+	vertex2=edge.end_vertex
+	c1=vertex1.system_data
+	c2=vertex2.system_data
+	model1=systemutils.get_specify_type_parent(vertex1,graph_model.FloorGraph).model
+	model2 = systemutils.get_specify_type_parent(vertex2, graph_model.FloorGraph).model
 	sql="insert into revit.connected_block" \
 		"(id1,type1,model_id1,id2,type2,model_id2,block_id,project_id) values " \
 		"('%s','%s','%s','%s','%s','%s','%s','%s')"\
-		%(vertex1.id,vertex1.type,vertex1.model_id,vertex2.id,vertex2.type,vertex2.model_id,block_id,project_id)
+		%(c1.id,c1.type,model1.file_id,c2.id,c2.type,model2.file_id,block_id,model1.project_id)
+	data = test.save_data(sql)
+def del_project_data(project_id):
+	"""
+	Before save.delete old data.
+	:param project_id:
+	:return:
+	"""
+	sql = "delete from revit.connected_block where project_id='%s'"% (project_id)
 	data = test.save_data(sql)
 if '__main__'==__name__:
-	model_id="cf4e11a0e25811e999b6dbc4c75fa946"
-	system_name="喷淋管"
-	domain="DomainPiping"
-	g=get_connectors_data(model_id,system_name,domain)
-	print (g)
+	# model_id="cf4e11a0e25811e999b6dbc4c75fa946"
+	# system_name="喷淋管"
+	# domain="DomainPiping"
+	# g=get_connectors_data(model_id,system_name,domain)
+	# print (g)
+	project_id='Pj1101010015'
+	models=get_project_models(project_id)
+	print(models)

+ 37 - 2
systemrelation/systemgraph_display.py

@@ -2,12 +2,47 @@ import networkx as nx
 import matplotlib.pyplot as plt
 
 def show_system(system_graph):
+	'''
+	Show one system by pyplot.
+	:param system_graph:
+	:return:
+	'''
 	g=nx.Graph()
 	for e in system_graph.system_edges:
-		g.add_edge(e.start_vertex.system_data.source_id,e.end_vertex.system_data.source_id)
+		#g.add_edge(e.start_vertex.system_data.source_id,e.end_vertex.system_data.source_id)
+		g.add_edge(e.start_vertex, e.end_vertex)
 	nx.draw(g,with_labels=True)
 	plt.show()
 
 def show_floor(floor_graph):
+	'''
+	Show all system in this floor
+	:param floor_graph:
+	:return:
+	'''
 	for s in floor_graph.system_graphs:
-		show_system(s)
+		show_system(s)
+
+def show_project(project_graph):
+	'''
+	Show all grouped system in project.
+	:param project_graph:
+	:return:
+	'''
+	for g in project_graph.groupedsystemgraphs:
+		show_groupedsystem(g)
+
+def show_groupedsystem(grouped_system_graph):
+	'''
+	Show one grouped system.
+	:param grouped_system_graph:
+	:return:
+	'''
+	g=nx.Graph()
+	for s in grouped_system_graph.systemgraphs:
+		for e in s.system_edges:
+			g.add_edge(e.start_vertex, e.end_vertex)
+	for e in grouped_system_graph.connectedges:
+			g.add_edge(e.start_vertex, e.end_vertex)
+	nx.draw(g,with_labels=True)
+	plt.show()

+ 77 - 8
systemrelation/systemutils.py

@@ -5,6 +5,9 @@
 
 from systemrelation import revit_const
 from functools import cmp_to_key
+import vg
+from systemrelation import graph_model
+
 
 def path2edge(elements):
 	"""
@@ -27,7 +30,7 @@ def graph_arrange(graph):
 def connector_sort(connector1, connector2):
 	"""Use Define Sort rule"""
 	dic = {revit_const.EQUIPMENT: 0, revit_const.COMPONENT: 1, revit_const.OTHER: 2, revit_const.PIPE: 3,
-			revit_const.DUCT: 4}
+		   revit_const.DUCT: 4}
 	x = dic[connector1.belong_type]
 	y = dic[connector2.belong_type]
 	return 1 if x > y else -1
@@ -35,7 +38,7 @@ def connector_sort(connector1, connector2):
 
 def sort_connectors(connectors):
 	"""Sort Connector order by Equipment>EquipPart>Other>Pipe>Duct"""
-	return sorted(connectors, key=cmp_to_key(lambda x,y:connector_sort(x,y)))
+	return sorted(connectors, key=cmp_to_key(lambda x, y: connector_sort(x, y)))
 
 
 def is_break_condition(element):
@@ -59,12 +62,78 @@ def dic2obj(d):
 			setattr(top, i, j)
 	return top
 
+
 def list_to_dict(lis):
-    ids = [idx.id for idx in lis]
-    dic = dict(zip(ids, lis))
-    return dic
+	ids = [idx.id for idx in lis]
+	dic = dict(zip(ids, lis))
+	return dic
+
 
 def add_attr_is_used(x):
-	""""""
-	x.is_used=False
-	return x
+	"""
+	Add is_used attribute.
+	:param x:
+	:return:
+	"""
+	x.is_used = False
+	return x
+
+
+def is_xyz_equal(origin1, origin2):
+	"""
+	Judge the two origin are almost equal.
+	:param origin1:
+	:param origin2:
+	:return:
+	"""
+	v1 = [origin1.X, origin1.Y, origin1.Z]
+	v2 = [origin2.X, origin2.Y, origin2.Z]
+	return vg.almost_equal(v1, v2, atol=1e-08)
+
+
+def combine_systemgraph(floorgraphs):
+	"""
+	Consider the riser merger
+	:param floorgraphs:
+	:return:projectgraph
+	"""
+	# get all open vertical pipe
+	open_vertical_pipes = []
+	for floorgraph in floorgraphs:
+		for systemgraph in floorgraph.system_graphs:
+			open_vertical_pipes.extend(systemgraph.get_open_vertical_pipes())
+	# group systemvertex
+	projectgraph = graph_model.ProjectGraph()
+	for i in range(len(open_vertical_pipes)):
+		v1 = open_vertical_pipes[i]
+		group_pipes = [v1]
+		for j in range(i + 1, len(open_vertical_pipes)):
+			v2 = open_vertical_pipes[j]
+			if is_xyz_equal(v1.connector.origin, v2.connector.origin):
+				group_pipes.append(v2)
+			# combine systemgraph
+			for k in range(len(group_pipes)):
+				vertex = group_pipes[k]
+				systemgraph = get_specify_type_parent(vertex,graph_model.SystemGraph)
+				if not systemgraph:
+					continue
+				projectgraph.remove_groupedsystemgraphs(systemgraph)
+				if (k == 0):
+					temp_groupedsystemgraphs = graph_model.GroupedSystemGraph(systemgraph)
+				else:
+					prev_vertex = group_pipes[k - 1]
+					temp_groupedsystemgraphs.add_system(systemgraph)
+					temp_groupedsystemgraphs.add_edge(prev_vertex, vertex)
+			if temp_groupedsystemgraphs:
+				projectgraph.groupedsystemgraphs.append(temp_groupedsystemgraphs)
+	return projectgraph
+
+def get_specify_type_parent(vertex, type):
+	parent = vertex
+	try:
+		while not isinstance(parent, type):
+			parent = parent.parent
+	except :
+		parent=None
+
+	return parent

+ 2 - 2
test.py

@@ -13,7 +13,7 @@ def save_data(sql):
             database='datacenter',
             user='postgres',
             password='123456',
-            host='192.168.20.235',
+            host='192.168.20.234',
             port='5432'
         )
         cursor = connection.cursor()
@@ -36,7 +36,7 @@ def get_data(sql):
             database='datacenter',
             user='postgres',
             password='123456',
-            host='192.168.20.235',
+            host='192.168.20.234',
             port='5432'
         )
         cursor = connection.cursor()