Browse Source

Merge remote-tracking branch 'origin/master'

jxing 5 years ago
parent
commit
b7eaf78937

+ 0 - 0
src/space_relation/__init__.py


+ 97 - 0
src/space_relation/calc_spaceadjoinrelation.py

@@ -0,0 +1,97 @@
+from relations import utils
+from shapely.geometry import Polygon
+def calc_plane(space_datas):
+	'''Calc plane business space adjoin relation.
+	:param floor_id:
+	:param space_type:
+	:return:
+	'''
+	relationcollection = utils.BinaryRelationCollection()
+	for i in range(len(space_datas)):
+		for j in range(i+1,len(space_datas)):
+			relations=calc_adjoinspace(space_datas[i],space_datas[j])
+			relationcollection.extend(relations)
+	return relationcollection
+
+def calc_verticalface(space_datas1,space_datas2):
+	'''Calc vertical business space adjoin relaiton.
+	:param floor_id1:
+	:param floor_id2:
+	:param space_type:
+	:return:
+	'''
+	relationcollection = utils.BinaryRelationCollection()
+	for s1 in space_datas1:
+		for s2 in space_datas2:
+			relations = calc_adjoinspace(s1, s2)
+			relationcollection.extend(relations)
+	return relationcollection
+
+def calc_adjoinspace(space,target_spaces):
+	'''Judge business space adjoin to other target_spaces.
+	:param space:
+	:param target_spaces:
+	:return:
+	'''
+	relationcollection=utils.BinaryRelationCollection()
+	for target in target_spaces:
+		if(judge_space(space,target)):
+			relationitem=utils.BinaryRelationItem(space.id,target.id)
+			relationcollection.update(relationitem)
+	return relationcollection
+def judge_space(space,target_space):
+	'''Judge business space adjoin relation.
+	business space may contain more than one basespace
+	:param space:
+	:param target_space:
+	:return:
+	'''
+	for b1 in space.outline2:
+		for b2 in target_space.outline2:
+			# find one,break
+			if(judge_space(b1,b2)):
+				return True
+	return False
+def judge_bspace(b1,b2):
+	'''Judge base space b1,b2 adjoin relation.
+	1. b1 outer polygon intersect b2 out polygon;
+	2. if b1 outer contain b2 outer,judge whether b1 inner contain b2, if true not adjoin,break;
+	3. exchange b1 b2.perform to step2;
+	:param b1:
+	:param b2:
+	:return:
+	'''
+	if(len(b1)<1 or len(b2)<1):
+		return False
+	p1_outer=convert2polygon(b1[0])
+	p2_outer=convert2polygon(b2[0])
+	# judge intersect.
+	result=p1_outer.intersects(p2_outer)
+	if(result):
+		# judge contain,outer contain and inner not contain.
+		result=judge_bspace_contain(p1_outer,p2_outer,b1)
+		if(result):
+			result=judge_bspace_contain(p2_outer, p1_outer, b2)
+	return result
+def judge_bspace_contain(p1_outer,p2_outer,b1):
+	'''Intersect space ,calc contain  relation .
+	:param p1_outer:big outer
+	:param p2_outer:small outer
+	:param b1:big space outline
+	:return:
+	'''
+	result=True
+	if (p1_outer.contains(p2_outer)):
+		for i in range(1, len(b1)):
+			inner = b1[i]
+			p_inner = convert2polygon(inner)
+			if (p_inner.contains(p2_outer)):
+				result = False
+				break
+	return result
+def convert2polygon(p):
+	coords =[]
+	for xyz in p:
+		coords.append((xyz.X,xyz.Y))
+	poly = Polygon(coords)
+	return poly

+ 32 - 0
src/space_relation/space_datautils.py

@@ -0,0 +1,32 @@
+'''Get space from database.
+
+'''
+from relations import test
+def get_space_data(floor_id,space_type):
+	'''Cache space from database by floor_id,space_type.
+	:param floor_id:
+	:param space_type:
+	:return:
+	'''
+	sql = "select " \
+		  "id,name,local_id,local_name,floor_id,outline,object_type" \
+		  "from zone_space_base " \
+		  "where floor_id='%s' " \
+		  "and object_type='%s' " \
+		  % (floor_id, space_type)
+
+	COMPONENT_KEYS = [
+		'id',
+		'name',
+		'local_id',
+		'local_name',
+		'floor_id',
+		'outline',
+		'object_type'
+	]
+	data = test.get_data(sql)
+	element_data = []
+	element_data.extend(utils.get_dicdata(data, COMPONENT_KEYS))
+	element_data = list(map(utils.dic2obj, element_data))
+	objects = utils.sqldata2objlist(element_data)
+	return objects

+ 14 - 0
src/space_relation/test.py

@@ -0,0 +1,14 @@
+import sys
+sys.path.append("../../..")
+from relations.src.space_relation import space_datautils, calc_spaceadjoinrelation
+
+if __name__=='__main__':
+	floor_id=''
+	object_type=''
+	floor_id2 = ''
+	spaces=space_datautils.get_space_data(floor_id,object_type)
+	spaces2 = space_datautils.get_space_data(floor_id2, object_type)
+	calc_spaceadjoinrelation.calc_plane(spaces)
+	calc_spaceadjoinrelation.calc_verticalface(spaces,spaces2)
+
+

+ 5 - 7
src/system_relation/calc_flowdirection.py

@@ -3,25 +3,22 @@ step1. division block.
 step2. appoint source.
 setp3. calc flow direction.
 '''
-from src.system_relation import systemdatautils
+from relations.src.system_relation import systemdatautils
 import networkx as nx
 
-
-def calc(project_id,block_id):
+def calc(block_datas,source_datas):
 	'''
 	calc block flow direction.
 	:param project_id:
 	:param block_id:
 	:return:
 	'''
-	block_datas= systemdatautils.get_connected_block_data(project_id, block_id)
-	source_datas= systemdatautils.get_connected_block_source_data(project_id, block_id)
 	# get roots
 	roots=list(i.source_id for i in source_datas)
 	g = nx.Graph()
 	for item in block_datas:
 		item.direction=None
-		g.add_edge(item.id1,item.id2);
+		g.add_edge(item.id1,item.id2)
 	G = g.to_directed()
 	# get leaves
 	leaves=list(v for v,d in G.out_degree() if d==1)
@@ -29,6 +26,7 @@ def calc(project_id,block_id):
 	try:
 		for i in range(len(roots)):
 			root=roots[i]
+			sign=1 if source_datas[i].is_source else -1
 			for leaf in leaves:
 				paths = nx.all_simple_paths(G, root, leaf)
 				for path in paths:
@@ -37,7 +35,7 @@ def calc(project_id,block_id):
 						continue
 					# set path direction
 					for j in range(len(path) - 1):
-						G_new.add_edge(path[j], path[j + 1],weight=(j))
+						G_new.add_edge(path[j], path[j + 1],weight=(j*sign))
 			# add source direct to source path.
 			for j in range(i + 1, len(roots)):
 				next_root=roots[j]

+ 12 - 12
src/system_relation/graph_model.py

@@ -1,7 +1,7 @@
 """Graph Model.
 """
 from enum import Enum
-import systemutils, revit_const, systemdatautils,graph_model
+from relations.src.system_relation import systemutils, revit_const, systemdatautils,graph_model
 
 
 class SystemVertex:
@@ -15,7 +15,7 @@ class SystemVertex:
 		self.parent= parent
 
 	def __str__(self):
-		return str(systemutils.get_specify_type_parent(self, FloorGraph).model.floor_name) + ':' + str(self.system_data.source_id)
+		return str(systemutils.get_specify_type_parent(self, FloorGraph).model.local_name) + ':' + str(self.system_data.source_id)
 
 	def __eq__(self, other):
 		return self.system_data.source_id==other.system_data.source_id
@@ -37,7 +37,7 @@ class SystemVertex:
 		Get relation floorgraph.
 		:return:
 		'''
-		model = systemutils.get_specify_type_parent(self, graph_model.FloorGraph).model
+		model = systemutils.get_specify_type_parent(self, graph_model.FloorGraph)
 		return model
 class SystemEdge:
 	"""Graph Edge."""
@@ -103,15 +103,14 @@ class FloorGraph:
 	May contain one or more SystemGraph.
 	"""
 
-	def __init__(self,model, system_name, domain):
-		self.model=model;
+	def __init__(self,model, system_name, domain,floor_connectors,element_data):
+		self.model=model
 		self.system_name = system_name
 		self.domain = 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(self.model.file_id))
+		self.connector_data = floor_connectors
+		self.element_data = systemutils.list_to_dict(element_data)
 		self.system_graphs = []
 
 	def get_floor_graphs(self):
@@ -204,7 +203,7 @@ class FloorGraph:
 		:return:
 		"""
 		cons = list(c for c in self.connector_data if c.id == connector_id)
-		return cons[0]
+		return cons[0] if len(cons)>0 else None
 
 	def get_element(self, element_id):
 		"""
@@ -247,7 +246,8 @@ class ProjectGraph:
 	'''
 	ProjectGraph contain more than one GroupedSystemGraph.
 	'''
-	def __init__(self):
+	def __init__(self,project_id):
+		self.project_id=project_id
 		self.groupedsystemgraphs=[]
 
 	def remove_groupedsystemgraphs(self, systemgraph):
@@ -282,7 +282,7 @@ class SystemVertexType(Enum):
 	hollow_dot = 2
 
 
-def combine_systemgraph(floorgraphs):
+def combine_systemgraph(project_id,floorgraphs):
 	"""
 	Consider the riser merger
 	:param floorgraphs:
@@ -294,7 +294,7 @@ def combine_systemgraph(floorgraphs):
 		for systemgraph in floorgraph.system_graphs:
 			open_vertical_pipes.extend(systemgraph.get_open_vertical_pipes())
 	# group systemvertex
-	projectgraph = graph_model.ProjectGraph()
+	projectgraph = graph_model.ProjectGraph(project_id)
 	for i in range(len(open_vertical_pipes)):
 		v1 = open_vertical_pipes[i]
 		group_pipes = [v1]

+ 1 - 0
src/system_relation/revit_const.py

@@ -4,6 +4,7 @@
 EQUIPMENT='Equipment'
 COMPONENT='EquipPart'
 FACILITY=[EQUIPMENT,COMPONENT]
+JoinObject='JoinObject'
 OTHER='Other'
 CONNECTOR='Connector'
 DUCT='Duct'

+ 0 - 751
src/system_relation/system_block.py

@@ -1,751 +0,0 @@
-"""const.
-
-"""
-EQUIPMENT='Equipment'
-COMPONENT='EquipPart'
-FACILITY=[EQUIPMENT,COMPONENT]
-OTHER='Other'
-CONNECTOR='Connector'
-DUCT='Duct'
-PIPE='Pipe'
-MEPCURVE=[DUCT,PIPE]
-
-"""system calc utils.
-1. get connectors where model_id='@model_id' and belong_type='Equipment' and mep_system_type='@system_name'
-2. get path start with connector,end with triple ,cross,equipment,end
-"""
-
-from functools import cmp_to_key
-import vg
-
-
-def path2edge(elements):
-	"""
-	Convert path to GraphtEdge
-	:param elements:
-	:return:
-	"""
-	pass
-
-
-def graph_arrange(graph):
-	"""
-	Combine Vertex that connect to virtul Vertex
-	:param graph:
-	:return:
-	"""
-	pass
-
-
-def connector_sort(connector1, connector2):
-	"""Use Define Sort rule"""
-	dic = {EQUIPMENT: 0, COMPONENT: 1, OTHER: 2, PIPE: 3,
-		   DUCT: 4}
-	x = dic[connector1.belong_type]
-	y = dic[connector2.belong_type]
-	return 1 if x > y else -1
-
-
-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)))
-
-
-def is_break_condition(element):
-	"""Path end Condition."""
-	res = element.type in revit_const.FACILITY
-	return res
-
-
-def dic2obj(d):
-	"""Convert Dict to Object.
-	"""
-	top = type('new', (object,), d)
-	seqs = tuple, list, set, frozenset
-	for i, j in d.items():
-		if isinstance(j, dict):
-			setattr(top, i, dic2obj(j))
-		elif isinstance(j, seqs):
-			setattr(top, i,
-					type(j)(dic2obj(sj) if isinstance(sj, dict) else sj for sj in j))
-		else:
-			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
-
-
-def add_attr_is_used(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 get_specify_type_parent(vertex, type):
-	parent = vertex
-	try:
-		while not isinstance(parent, type):
-			parent = parent.parent
-	except :
-		parent=None
-
-	return parent
-
-
-"""PipeNetwork Data .
-
-"""
-import test
-
-
-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(dic2obj, element_data))
-	return element_data
-def get_element_data(model_id):
-	"""
-	Cache all Element from Db
-	:return:
-	"""
-	element_data=[]
-	component_sql="select * from revit.component where model_id='%s'"%(model_id)
-	COMPONENT_KEYS = [
-		'id',
-		'model_id',
-		'local_id',
-		'local_name',
-		'family',
-		'location',
-		'outline',
-		'source_id',
-		'name',
-		'revit_id',
-		'parameters',
-		'type',
-		'tag',
-		'owner',
-		'last_update',
-		'create_time',
-		'owner_id',
-		'family_name',
-		'owner_source_id'
-	]
-	element_data.extend(get_dicdata(component_sql,COMPONENT_KEYS))
-
-	equipment_sql="select * from revit.equipment where model_id='%s'"%(model_id)
-	EQUIPMENT_KEYS = [
-		'id',
-		'model_id',
-		'local_id',
-		'local_name',
-		'family',
-		'location',
-		'outline',
-		'last_update',
-		'create_time',
-		'source_id',
-		'name',
-		'parameters',
-		'revit_id',
-		'type',
-		'tag',
-		'family_name',
-	]
-	element_data.extend(get_dicdata(equipment_sql,EQUIPMENT_KEYS))
-
-	other_sql="select * from revit.other where model_id='%s'"%(model_id)
-	OTHER_KEYS = [
-		'id',
-		'model_id',
-		'connected_ids',
-		'source_id',
-		'name',
-		'revit_id',
-		'type',
-		'create_time',
-		'last_update',
-		'location',
-		'outline'
-	]
-	element_data.extend(get_dicdata(other_sql,OTHER_KEYS))
-
-	pipe_sql = "select * from revit.pipe where model_id='%s'" % (model_id)
-	PIPE_KEYS = [
-		'id',
-		'model_id',
-		'location',
-		'outline',
-		'connected_ids',
-		'mep_system_type',
-		'diameter',
-		'source_id',
-		'name',
-		'revit_id',
-		'type',
-		'last_update',
-		'create_time',
-		'parameters'
-	]
-	element_data.extend(get_dicdata(pipe_sql, PIPE_KEYS))
-
-	duct_sql="select * from revit.duct where model_id='%s'"%(model_id)
-	DUCT_KEYS = [
-		'id',
-		'model_id',
-		'location',
-		'outline',
-		'connected_ids',
-		'mep_system_type',
-		'shape',
-		'diameter',
-		'width',
-		'height',
-		'source_id',
-		'revit_id',
-		'name',
-		'type',
-		'last_update',
-		'create_time',
-		'parameters'
-	]
-	element_data.extend(get_dicdata(duct_sql,DUCT_KEYS))
-	element_data=list(map(dic2obj, element_data))
-	return element_data
-
-
-def get_connectors_data(model_id, system_name, domain):
-	"""Cache all connector from Db。"""
-	connector_data=[]
-	connector_sql = "SELECT * FROM revit.connector where model_id='%s' and mep_system_type='%s' and domain='%s'" % (model_id,system_name,domain)
-	print(connector_sql)
-	CONNECTOR_KEYS = [
-		'id',
-		'model_id',
-		'belong',
-		'belong_type',
-		'origin',
-		'domain',
-		'description',
-		'connected',
-		'owner',
-		'connected_ids',
-		'mep_system_type',
-		'source_id',
-		'revit_id',
-		'type',
-		'create_time',
-		'last_update',
-		'connect_id_json'
-	]
-	connector_data.extend(get_dicdata(connector_sql, CONNECTOR_KEYS))
-	connector_data=list(map(dic2obj, connector_data))
-	return connector_data
-
-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 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 save_edge_data(edge,block_id):
-	"""
-	Save edge info using sql
-	:param edge:
-	:param block_id:
-	:return:
-	"""
-	try:
-		vertex1=edge.start_vertex
-		vertex2=edge.end_vertex
-		c1=vertex1.system_data
-		c2=vertex2.system_data
-		model1= vertex1.get_parent_floor()
-		model2 = vertex2.get_parent_floor()
-		sql="insert into revit_calc.connected_block" \
-			"(id1,type1,model_id1,id2,type2,model_id2,block_id,project_id) values " \
-			"('%s','%s','%s','%s','%s','%s','%s','%s')"\
-			%(c1.id,c1.type,model1.file_id,c2.id,c2.type,model2.file_id,block_id,model1.project_id)
-		data = test.save_data(sql)
-	except Exception as e:
-		print(e)
-def del_project_data(project_id):
-	"""
-	Before save.delete old data.
-	:param project_id:
-	:return:
-	"""
-	sql = "delete from revit_calc.connected_block where project_id='%s'"% (project_id)
-	data = test.save_data(sql)
-def get_connected_block_data(project_id,block_id):
-	'''
-	Get all the connected_block .
-	:param project_id:
-	:param block_id:
-	:return:
-	'''
-	element_data = []
-	sql = "select * from revit_calc.connected_block " \
-		  "where project_id='%s'" \
-		  "and block_id='%s'" \
-		  "order by cast(depth as int) asc"\
-		  % (project_id,block_id)
-	KEYS = [
-		'id',
-		'id1',
-		'type1',
-		'model_id1',
-		'id2',
-		'type2',
-		'model_id2',
-		'direction',
-		'block_id',
-		'project_id',
-		'depth',
-	]
-	element_data.extend(get_dicdata(sql, KEYS))
-	element_data = list(map(dic2obj, element_data))
-	return element_data
-def get_connected_block_source_data(project_id,block_id):
-	'''
-	Get all the connected_block source .
-	:param project_id:
-	:param block_id:
-	:return:
-	'''
-	element_data = []
-	sql = "select * from revit_calc.connected_block_source " \
-		  "where project_id='%s'" \
-		  "and block_id='%s'" \
-		  % (project_id,block_id)
-	KEYS = [
-		'id',
-		'project_id',
-		'block_id',
-		'source_id',
-	]
-	element_data.extend(get_dicdata(sql, KEYS))
-	element_data = list(map(dic2obj, element_data))
-	return element_data
-def update_connected_block_data(block_datas):
-	'''
-	update connected_block direction by id.
-	:param block_datas:
-	:return:
-	'''
-	for block_data in block_datas:
-		sql="update revit_calc.connected_block set direction='%s',depth='%s' where id='%s'"\
-			%(block_data.direction,block_data.depth,block_data.id)
-		data = test.save_data(sql)
-
-
-"""Graph Model.
-"""
-from enum import Enum
-
-
-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(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 MEPCURVE):
-				return True
-		return False
-	def get_parent_floor(self):
-		'''
-		Get relation floorgraph.
-		:return:
-		'''
-		model = get_specify_type_parent(self, FloorGraph).model
-		return model
-class SystemEdge:
-	"""Graph Edge."""
-	# edge data.contain all edge element
-	flow_direction = 0
-
-	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
-#
-# @property
-# def end_vertex(self):
-# 	return self.end_vertex
-
-
-class SystemGraph:
-	"""System Graph
-	"""
-	# system edge array.
-	system_graph_id = ''
-	# system type Name
-	system_name = ""
-
-	def __init__(self,parent):
-		self.system_edges = []
-		self.parent=parent
-
-	def add_edge(self, c1, c2, elements):
-		"""
-		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,model, system_name, domain):
-		self.model=model;
-		self.system_name = system_name
-		self.domain = domain
-		floor_connectors = get_connectors_data(self.model.file_id, system_name, domain)
-		floor_connectors = sort_connectors(floor_connectors)
-		floor_connectors = list(map(add_attr_is_used, floor_connectors))
-		self.connector_data = (floor_connectors)
-		self.element_data = list_to_dict(get_element_data(self.model.file_id))
-		self.system_graphs = []
-
-	def get_floor_graphs(self):
-		"""Get current floor graph.
-		system_name,domain
-		"""
-		for connector in self.connector_data:
-			system_graph = SystemGraph(self)
-			graph_next_connectors = [connector]
-			# dept-first
-			for connector in graph_next_connectors:
-				self.get_path(connector, system_graph, graph_next_connectors)
-			if len(system_graph.system_edges) != 0:
-				self.system_graphs.append(system_graph)
-				print("Next loop:",connector.source_id)
-		return self.system_graphs
-
-	def get_path(self, connector, system_graph, graph_next_connectors):
-		"""
-		Get Graph_Edge start with connector,end with triple ,cross,equipment.
-		:param connector:
-		:return:Graph_Edge
-		"""
-		system_edge = None
-		if (connector.is_used):
-			return system_edge
-		try:
-			#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
-			while (current_connector is not None):
-				current_connector.is_used = True
-				connecteds = self.get_connecteds(current_connector.connect_id_json)
-				if len(connecteds) > 1:
-					raise Exception("connected to many.connector_id:", current_connector.connect_id_json)
-				#Open Connector
-				if len(connecteds) == 0:
-					if current_connector != connector:
-						system_edge = system_graph.add_edge(connector, current_connector, edge_elements)
-					break
-				next_connector = connecteds[0]
-				if next_connector is not None and next_connector.domain == connector.domain and next_connector.mep_system_type == connector.mep_system_type:
-					next_element = self.get_element(next_connector.belong)
-					edge_elements.append(next_element)
-					other_connectors = self.get_other_connectors(next_connector)
-					if is_break_condition(next_element) or len(other_connectors) != 1:
-						print(next_connector.source_id)
-						next_connector.is_used = True
-						if(len(other_connectors) != 1):
-							graph_next_connectors.extend(other_connectors)
-						system_edge = system_graph.add_edge(connector, next_connector, edge_elements)
-						break
-					if len(other_connectors)==1:
-						next_connector.is_used = True
-						current_connector = other_connectors[0]
-						continue
-				current_connector = None
-		except Exception as e:
-			print(e)
-
-		return system_edge
-
-	def get_other_connectors(self, use_connector):
-		"""
-		Get the  connector owner other connectors.
-		belong,domian,mep_system_type same.
-		is_used==False.
-		:param use_connector:
-		:return:
-		"""
-		connectors = [connector for connector in self.connector_data if
-					  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]
-		connectors = [connector for connector in connectors if bool(1 - connector.is_used)]
-		return connectors
-
-	def get_connecteds(self, connetor_id):
-		"""
-		Get Ref Connector. may have two.like system logic connector
-		:param connetor_id:
-		:return:
-		"""
-		connectors = list(self.get_connector(id) for id in connetor_id)
-		return connectors
-
-	def get_connector(self, connector_id):
-		"""
-		Get Connector by Id.
-		:param connector_id:
-		:return:
-		"""
-		cons = list(c for c in self.connector_data if c.id == connector_id)
-		return cons[0]
-
-	def get_element(self, element_id):
-		"""
-		Get Element by Id.
-		:param eleemnt_id:
-		:return:
-		"""
-		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.
-	"""
-	flow_in = 1
-	flow_out = -1
-	flow_undefine = 0
-
-
-class SystemVertexType(Enum):
-	"""Vertex Type.
-	"""
-	real_point = 0
-	imaginary_point = 1
-	hollow_dot = 2
-
-
-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 = 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, SystemGraph)
-				if not systemgraph:
-					continue
-				projectgraph.remove_groupedsystemgraphs(systemgraph)
-				if (k == 0):
-					temp_groupedsystemgraphs = 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
-
-if '__main__'==__name__:
-	project_id="Pj1101010015"
-	system_name="冷冻水供水管"
-	domain="DomainPiping"
-	models= get_project_models(project_id)
-	floorgraphs=[]
-	for model in models:
-		g= FloorGraph(model, system_name, domain)
-		g.get_floor_graphs()
-		floorgraphs.append(g)
-	projectgraph= combine_systemgraph(floorgraphs)
-	save_project_data(projectgraph, project_id)
-	#systemgraph_display.show_project(projectgraph)

+ 76 - 47
src/system_relation/systemdatautils.py

@@ -2,7 +2,7 @@
 
 """
 import test
-import systemutils
+from relations.src.system_relation import systemutils
 
 
 def get_dicdata(sql,dic):
@@ -16,7 +16,7 @@ def get_dicdata(sql,dic):
 	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):
+def get_project_models(project_id,building_id):
 	'''
 	Get all the models in the project.
 	project-->folder-->model.
@@ -24,34 +24,25 @@ def get_project_models(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 "\
+	sql="select " \
+		"id,name,local_id,local_name,sequence_id,model_id,building_id,project_id " \
+		"from floor " \
+		"where project_id='%s' " \
+		"and ('%s' is null or building_id='%s') " \
+		"order by sequence_id desc" \
+		% (project_id, building_id, building_id)
+		# "order by sequence_id desc"\
+		# %(project_id)
+
+
 	COMPONENT_KEYS = [
-		'file_id',
-		'file_name',
-		'file_status',
-		'floor_id',
-		'floor_name',
-		'folder_id',
-		'folder_name',
+		'id',
+		'name',
+		'local_id',
+		'local_name',
+		'sequence_id',
+		'model_id',
+		'building_id',
 		'project_id'
 	]
 	element_data.extend(get_dicdata(sql, COMPONENT_KEYS))
@@ -124,6 +115,22 @@ def get_element_data(model_id):
 	]
 	element_data.extend(get_dicdata(other_sql,OTHER_KEYS))
 
+	other_sql = "select * from revit.join_object where model_id='%s'" % (model_id)
+	OTHER_KEYS = [
+		'id',
+		'model_id',
+		'connected_ids',
+		'source_id',
+		'name',
+		'revit_id',
+		'type',
+		'create_time',
+		'last_update',
+		'location',
+		'outline'
+	]
+	element_data.extend(get_dicdata(other_sql, OTHER_KEYS))
+
 	pipe_sql = "select * from revit.pipe where model_id='%s'" % (model_id)
 	PIPE_KEYS = [
 		'id',
@@ -196,23 +203,23 @@ def get_connectors_data(model_id, system_name, domain):
 	connector_data=list(map(systemutils.dic2obj, connector_data))
 	return connector_data
 
-def save_project_data(project_graph,project_id):
+def save_project_data(project_graph,system_name,domain,building_id):
 	"""
 	Sava project graph data.
 	:param floor_graph:
 	:return:
 	"""
-	del_project_data(project_id)
+	del_project_data(project_graph.project_id,system_name,domain,building_id)
 	# Create
 	block_id=0
 	for g in project_graph.groupedsystemgraphs:
 		for s in g.systemgraphs:
 			for e in s.system_edges:
-				save_edge_data(e, block_id)
+				save_edge_data(e, block_id,building_id)
 		for e in g.connectedges:
-			save_edge_data(e,block_id)
+			save_edge_data(e,block_id,building_id)
 		block_id+=1
-def save_edge_data(edge,block_id):
+def save_edge_data(edge,block_id,building_id):
 	"""
 	Save edge info using sql
 	:param edge:
@@ -224,24 +231,31 @@ def save_edge_data(edge,block_id):
 		vertex2=edge.end_vertex
 		c1=vertex1.system_data
 		c2=vertex2.system_data
-		model1= vertex1.get_parent_floor()
-		model2 = vertex2.get_parent_floor()
+		floor1 = vertex1.get_parent_floor()
+		floor2 = vertex2.get_parent_floor()
+		model1= floor1.model
+		model2 = floor2.model
 		sql="insert into revit_calc.connected_block" \
-			"(id1,type1,model_id1,id2,type2,model_id2,block_id,project_id) values " \
-			"('%s','%s','%s','%s','%s','%s','%s','%s')"\
-			%(c1.id,c1.type,model1.file_id,c2.id,c2.type,model2.file_id,block_id,model1.project_id)
+			"(id1,type1,model_id1,id2,type2,model_id2,block_id,project_id,mep_system_type,domain,building_id) values " \
+			"('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')"\
+			%(c1.id,c1.type,model1.model_id,c2.id,c2.type,model2.model_id,block_id,model1.project_id,floor1.system_name,floor1.domain,building_id)
 		data = test.save_data(sql)
 	except Exception as e:
 		print(e)
-def del_project_data(project_id):
+def del_project_data(project_id,system_name,domain,building_id):
 	"""
 	Before save.delete old data.
 	:param project_id:
 	:return:
 	"""
-	sql = "delete from revit_calc.connected_block where project_id='%s'"% (project_id)
-	data = test.save_data(sql)
-def get_connected_block_data(project_id,block_id):
+	sql = "delete from revit_calc.connected_block " \
+		  "where project_id='%s'"\
+		  "and mep_system_type='%s'" \
+		  "and domain='%s'" \
+		  "and ('%s' is null or building_id='%s')" \
+		  % (project_id,system_name,domain,building_id,building_id)
+	test.save_data(sql)
+def get_connected_block_data(project_id,building_id,block_id,system_name,domain):
 	'''
 	Get all the connected_block .
 	:param project_id:
@@ -252,8 +266,11 @@ def get_connected_block_data(project_id,block_id):
 	sql = "select * from revit_calc.connected_block " \
 		  "where project_id='%s'" \
 		  "and block_id='%s'" \
+		  "and mep_system_type='%s'" \
+		  "and domain='%s'" \
+		  "and ('%s' is null or building_id='%s')" \
 		  "order by cast(depth as int) asc"\
-		  % (project_id,block_id)
+		  % (project_id,block_id,system_name,domain,building_id,building_id)
 	KEYS = [
 		'id',
 		'id1',
@@ -266,11 +283,14 @@ def get_connected_block_data(project_id,block_id):
 		'block_id',
 		'project_id',
 		'depth',
+		'mep_system_type',
+		'domain',
+		'building_id',
 	]
 	element_data.extend(get_dicdata(sql, KEYS))
 	element_data = list(map(systemutils.dic2obj, element_data))
 	return element_data
-def get_connected_block_source_data(project_id,block_id):
+def get_connected_block_source_data(project_id,building_id,block_id,system_name,domain,is_source):
 	'''
 	Get all the connected_block source .
 	:param project_id:
@@ -281,12 +301,21 @@ def get_connected_block_source_data(project_id,block_id):
 	sql = "select * from revit_calc.connected_block_source " \
 		  "where project_id='%s'" \
 		  "and block_id='%s'" \
-		  % (project_id,block_id)
+		  "and mep_system_type='%s'" \
+		  "and domain='%s'" \
+		  "and ('%s' is null or building_id='%s')" \
+		  "and is_source=%s" \
+		  % (project_id,block_id,system_name,domain,building_id,building_id,is_source)
 	KEYS = [
 		'id',
 		'project_id',
 		'block_id',
 		'source_id',
+		'source_type',
+		'mep_system_type',
+		'domain',
+		'building_id',
+		'is_source',
 	]
 	element_data.extend(get_dicdata(sql, KEYS))
 	element_data = list(map(systemutils.dic2obj, element_data))
@@ -298,7 +327,7 @@ def update_connected_block_data(block_datas):
 	:return:
 	'''
 	for block_data in block_datas:
-		sql="update revit_calc.connected_block set direction='%s',depth='%s' where id='%s'"\
+		sql="update revit_calc.connected_block set direction='%s',depth='%s' where id='%s'" \
 			%(block_data.direction,block_data.depth,block_data.id)
 		data = test.save_data(sql)
 

+ 8 - 9
src/system_relation/systemgraph_display.py

@@ -51,20 +51,19 @@ def show_groupedsystem(grouped_system_graph):
 from src.system_relation import systemdatautils
 
 
-def show_connected_block(project_id: object, block_id: object) -> object:
+def show_connected_block(block_datas):
 	'''
 	show connected block.
 	:param project_id:
 	:param block_id:
 	:return:
 	'''
-	block_datas= systemdatautils.get_connected_block_data(project_id, block_id)
 	g=nx.DiGraph()
 	model_dic = {}
 	floor_data_dic = {}
 	for block_data in block_datas:
-		v1=get_connected_info(model_dic,floor_data_dic,block_data.project_id,block_data.model_id1,block_data.type1,block_data.id1)
-		v2 = get_connected_info(model_dic,floor_data_dic,block_data.project_id,block_data.model_id2, block_data.type2, block_data.id2)
+		v1=get_connected_info(model_dic,floor_data_dic,block_data,block_data.model_id1,block_data.type1,block_data.id1)
+		v2 = get_connected_info(model_dic,floor_data_dic,block_data,block_data.model_id2, block_data.type2, block_data.id2)
 		direction=block_data.direction
 		if direction==1 or direction==0:
 			g.add_edge(v1,v2)
@@ -73,20 +72,20 @@ def show_connected_block(project_id: object, block_id: object) -> object:
 	nx.draw_planar(g, with_labels=True, font_size=8, with_label=True)
 	plt.show()
 
-def get_connected_info(model_dic,floor_data_dic,project_id,model_id,type,id):
+def get_connected_info(model_dic,floor_data_dic,block_data,model_id,type,id):
 	'''
 	get graphvertex display info
 	:param model_dic:
 	:param floor_data_dic:
-	:param project_id:
+	:param block_data:
 	:param model_id:
 	:param type:
 	:param id:
 	:return:
 	'''
 	if model_id not in model_dic:
-		models = systemdatautils.get_project_models(project_id)
-		ids=[i.file_id for i in models]
+		models = systemdatautils.get_project_models(block_data.project_id,block_data.building_id)
+		ids=[i.model_id for i in models]
 		model_dic=dict(zip(ids,models))
 	model=model_dic[model_id]
 	if model_id not in floor_data_dic:
@@ -96,5 +95,5 @@ def get_connected_info(model_dic,floor_data_dic,project_id,model_id,type,id):
 	datas=list(i for i in floor_datas if i.type==type and i.id==id)
 	str0=id
 	if datas:
-		str0=str(model.floor_name)+':'+str(datas[0].source_id)
+		str0=str(model.local_name)+':'+str(datas[0].source_id)
 	return str0

+ 22 - 8
src/system_relation/systemutils.py

@@ -5,7 +5,8 @@
 
 from functools import cmp_to_key
 import vg
-import relations.src.system_relation.revit_const
+import json
+from relations.src.system_relation import revit_const
 
 
 def path2edge(elements):
@@ -28,7 +29,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,
+	dic = {revit_const.EQUIPMENT: 0, revit_const.COMPONENT: 1,revit_const.JoinObject:2, revit_const.OTHER: 2, revit_const.PIPE: 3,
 		   revit_const.DUCT: 4}
 	x = dic[connector1.belong_type]
 	y = dic[connector2.belong_type]
@@ -52,18 +53,31 @@ def dic2obj(d):
 	top = type('new', (object,), d)
 	seqs = tuple, list, set, frozenset
 	for i, j in d.items():
-		if isinstance(j, dict):
-			setattr(top, i, dic2obj(j))
-		elif isinstance(j, seqs):
+		j0 = j
+		try:
+			j0 = json.loads(j0)
+		except Exception as e:
+			pass
+		if isinstance(j0, dict):
+			setattr(top, i, dic2obj(j0))
+		elif isinstance(j0, seqs):
 			setattr(top, i,
-					type(j)(dic2obj(sj) if isinstance(sj, dict) else sj for sj in j))
+					type(j0)(dic2obj(sj) if isinstance(sj, dict) else sj for sj in j0))
 		else:
-			setattr(top, i, j)
+			setattr(top, i, j0)
 	return top
 
+def sqldata2objlist(data):
+	'''Convert Sqldata to Object list.
+	'''
+	return list(map(dic2obj,data))
 
 def list_to_dict(lis):
-	ids = [idx.id for idx in lis]
+	'''Convert list to id Dict.
+	:param lis:
+	:return:
+	'''
+	ids = [idx.id for idx in lis if idx.id]
 	dic = dict(zip(ids, lis))
 	return dic
 

+ 11 - 4
src/system_relation/test_flowdirection.py

@@ -1,8 +1,15 @@
-import calc_flowdirection, systemdatautils
-
+import sys
+sys.path.append("../../..")
+from relations.src.system_relation import calc_flowdirection, systemdatautils,systemgraph_display
 if __name__=="__main__":
 	project_id="Pj1101010015"
 	block_id="0"
-	block_datas= calc_flowdirection.calc(project_id, block_id)
+	system_name = "冷冻水供水管"
+	domain = "DomainPiping"
+	building_id = 'Bd11010100153c05821ed8fd11e9b8f2d79d0a5b4bf6'
+	is_source=True
+	block_datas= systemdatautils.get_connected_block_data(project_id,building_id, block_id,system_name,domain)
+	source_datas= systemdatautils.get_connected_block_source_data(project_id,building_id, block_id,system_name,domain,is_source)
+	block_datas= calc_flowdirection.calc(block_datas, source_datas)
 	systemdatautils.update_connected_block_data(block_datas)
-	#systemgraph_display.show_connected_block(project_id,block_id)
+	systemgraph_display.show_connected_block(block_datas)

+ 12 - 7
src/system_relation/test_systemblock.py

@@ -1,16 +1,21 @@
-import systemutils, graph_model, systemdatautils
-
+import sys
+sys.path.append("../../..")
+from relations.src.system_relation import systemutils, graph_model, systemdatautils,systemgraph_display
 
+from cffi import FFI
 if '__main__'==__name__:
 	project_id="Pj1101010015"
 	system_name="冷冻水供水管"
 	domain="DomainPiping"
-	models= systemdatautils.get_project_models(project_id)
+	building_id = 'Bd11010100153c05821ed8fd11e9b8f2d79d0a5b4bf6'
+	models= systemdatautils.get_project_models(project_id,building_id)
 	floorgraphs=[]
 	for model in models:
-		g= graph_model.FloorGraph(model, system_name, domain)
+		floor_connectors = systemdatautils.get_connectors_data(model.model_id, system_name, domain)
+		floor_elements = systemdatautils.get_element_data(model.model_id)
+		g = graph_model.FloorGraph(model, system_name, domain, floor_connectors, floor_elements)
 		g.get_floor_graphs()
 		floorgraphs.append(g)
-	projectgraph= systemutils.combine_systemgraph(floorgraphs)
-	systemdatautils.save_project_data(projectgraph, project_id)
-	#systemgraph_display.show_project(projectgraph)
+	projectgraph= graph_model.combine_systemgraph(project_id,floorgraphs)
+	systemdatautils.save_project_data(projectgraph,system_name,domain,building_id)
+	systemgraph_display.show_project(projectgraph)

+ 41 - 0
utils.py

@@ -37,3 +37,44 @@ class BinaryRelationCollection(object):
 
     def __iter__(self):
         return iter(self.__m_Dic)
+
+
+from relations import test
+
+
+def dic2obj(d):
+    """Convert Dict to Object.
+    """
+    top = type('new', (object,), d)
+    seqs = tuple, list, set, frozenset
+    for i, j in d.items():
+        j0 = j
+        try:
+            j0 = json.loads(j0)
+        except Exception as e:
+            pass
+        if isinstance(j0, dict):
+            setattr(top, i, dic2obj(j0))
+        elif isinstance(j0, seqs):
+            setattr(top, i,
+                    type(j0)(dic2obj(sj) if isinstance(sj, dict) else sj for sj in j0))
+        else:
+            setattr(top, i, j0)
+    return top
+
+def sqldata2objlist(data):
+    '''Convert Sqldata to Object list.
+    '''
+    return list(map(dic2obj,data))
+
+
+def get_dicdata(data,dic):
+    """
+    Request db for data through sql.
+    Convert data to dict.
+    :param sql:
+    :param dic:
+    :return:
+    """
+    dic_data=[dict(zip(dic,item)) for item in data]
+    return list(dic_data)