You can now submit custom geometry for covetool environmental analysis

This commit is contained in:
Dion Moult
2020-05-29 19:18:57 +10:00
parent ec8a07ec6a
commit 7e77c0c92c
5 changed files with 122 additions and 2 deletions
@@ -213,6 +213,7 @@ if bpy is not None:
covetool_ui.BIM_PT_covetool,
covetool_operator.Login,
covetool_operator.RunSimpleAnalysis,
covetool_operator.RunAnalysis,
)
def menu_func_export(self, context):
@@ -159,7 +159,6 @@ class IfcParser():
self.styled_items = self.get_styled_items()
self.spatial_structure_elements = self.get_spatial_structure_elements()
self.groups = self.get_groups()
self.libraries = self.get_libraries()
self.door_attributes = self.get_door_attributes()
self.window_attributes = self.get_window_attributes()
@@ -15,7 +15,7 @@ class Api:
def post_request(self, path, data, use_token=True):
url = self._api_url(path)
headers = self._headers(use_token)
response = requests.post(url, headers=headers, data=data)
response = requests.post(url, headers=headers, json=data)
return self._handle_response(response)
def get_request(self, path, use_token=True):
@@ -61,3 +61,120 @@ class RunSimpleAnalysis(bpy.types.Operator):
covetool_results = bpy.data.texts.new('cove.tool Results')
covetool_results.write(json.dumps(result, indent=4))
return {'FINISHED'}
class RunAnalysis(bpy.types.Operator):
bl_idname = 'bim.covetool_run_analysis'
bl_label = 'Run Analysis'
def execute(self, context):
self.inputs = {
'floors': [],
'walls': [],
'interior_walls': [],
'windows': [],
'skylights': [],
'roofs': [],
'shading_devices': []
}
self.parse_objects()
data = {
'run': bpy.context.scene.CoveToolProperties.projects[bpy.context.scene.CoveToolProperties.active_project_index].run_set,
'source': 'BlenderBIM',
'rotation_angle': 0,
**self.inputs
}
result = api.post_request('run-values', data)
covetool_results = bpy.data.texts.new('cove.tool Results')
covetool_results.write(json.dumps(result, indent=4))
return {'FINISHED'}
def parse_objects(self):
for obj in bpy.context.visible_objects:
covetool_category = self.get_covetool_category(obj)
if not covetool_category:
continue
if not self.has_triangulate_modifier(obj):
obj.modifiers.new(name='Triangulate', type='TRIANGULATE')
mesh = obj.evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
meshes = {}
for polygon in mesh.polygons:
normal = '{}|{}|{}'.format(
round(polygon.normal[0], 2),
round(polygon.normal[1], 2),
round(polygon.normal[2], 2))
meshes.setdefault(normal, {
'Mesh': {
'vertex_indices': {},
'Vertices': [],
'Triangles': []
},
'Center': {},
'Normal': {
'X': round(polygon.normal[0], 2),
'Y': round(polygon.normal[1], 2),
'Z': round(polygon.normal[2], 2)
}
})
for vertex in polygon.vertices:
global_vertex = obj.matrix_world @ mesh.vertices[vertex].co
meshes[normal]['Mesh']['vertex_indices'][vertex] = {
'X': global_vertex[0] * 3.28084, # Covetools require feet
'Y': global_vertex[1] * 3.28084,
'Z': global_vertex[2] * 3.28084
}
meshes[normal]['Mesh']['Triangles'].append([
polygon.vertices[0],
polygon.vertices[1],
polygon.vertices[2]
])
for normal, mesh in meshes.items():
sorted_keys = sorted(mesh['Mesh']['vertex_indices'])
mesh['Mesh']['Vertices'] = [mesh['Mesh']['vertex_indices'][k] for k in sorted_keys]
for triangle in mesh['Mesh']['Triangles']:
triangle[0] = sorted_keys.index(triangle[0])
triangle[1] = sorted_keys.index(triangle[1])
triangle[2] = sorted_keys.index(triangle[2])
mesh['Center'] = mesh['Mesh']['Vertices'][0] # Not correct, but just for now
del mesh['Mesh']['vertex_indices']
self.inputs[covetool_category].extend(meshes.values())
def has_triangulate_modifier(self, obj):
for modifier in obj.modifiers:
if modifier.type == 'TRIANGULATE':
return True
def get_covetool_category(self, obj):
if not hasattr(obj, 'data') or not isinstance(obj.data, bpy.types.Mesh):
return
if 'IfcSlab' in obj.name:
return 'floors'
elif 'IfcRoof' in obj.name:
return 'roofs'
elif 'IfcWall' in obj.name:
if self.is_wall_internal(obj):
return 'interior_walls'
return 'walls'
elif 'IfcWindow' in obj.name:
if self.is_window_skylight(obj):
return 'skylights'
return 'windows'
elif 'IfcShadingDevice' in obj.name:
return 'shading_devices'
def is_wall_internal(self, obj):
pset_wallcommon = obj.BIMObjectProperties.psets.get('Pset_WallCommon')
if pset_wallcommon:
is_external = pset_wallcommon.properties.get('IsExternal')
if is_external:
if is_external.string_value == 'True':
return False
else:
return True
predefined_type = obj.BIMObjectProperties.attributes.get('PredefinedType')
if predefined_type and predefined_type.string_value in ['MOVABLE', 'PARTITIONING', 'PLUMBINGWALL']:
return True
def is_window_skylight(self, obj):
predefined_type = obj.BIMObjectProperties.attributes.get('PredefinedType')
return predefined_type and predefined_type.string_value == 'SKYLIGHT'
@@ -26,6 +26,9 @@ class BIM_PT_covetool(bpy.types.Panel):
layout.template_list('BIM_UL_covetool_projects', '', props, 'projects', props, 'active_project_index')
row = layout.row()
row.operator('bim.covetool_run_analysis')
prop_names = [ 'si_units', 'building_height', 'roof_area', 'floor_area',
'skylight_area', 'wall_area_e', 'wall_area_ne', 'wall_area_n',
'wall_area_nw', 'wall_area_w', 'wall_area_sw', 'wall_area_s',