Rename misleading "ifcblenderexport" directory to "blenderbim"

This commit is contained in:
Dion Moult
2021-03-26 20:44:14 +11:00
parent 074a8c287f
commit 6186a88568
244 changed files with 4 additions and 4 deletions
@@ -0,0 +1,21 @@
import bpy
from . import ui, prop, operator
classes = (
prop.CoveToolProject,
prop.CoveToolSimpleAnalysis,
prop.CoveToolProperties,
ui.BIM_UL_covetool_projects,
ui.BIM_PT_covetool,
operator.Login,
operator.RunSimpleAnalysis,
operator.RunAnalysis,
)
def register():
bpy.types.Scene.CoveToolProperties = bpy.props.PointerProperty(type=prop.CoveToolProperties)
def unregister():
del bpy.types.Scene.CoveToolProperties
@@ -0,0 +1,40 @@
import requests
class Api:
def login(self, username, password):
data = {
"username": username,
"password": password,
}
response_data = self.post_request("get-token", data, False)
if "token" in response_data:
self.token = str(response_data["token"])
return self.token
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, json=data)
return self._handle_response(response)
def get_request(self, path, use_token=True):
url = self._api_url(path)
headers = self._headers(use_token)
response = requests.get(url, headers=headers)
return self._handle_response(response)
def _api_url(self, path):
return "https://app.covetool.com/api/" + path + "/"
def _headers(self, use_token):
headers = {}
if use_token:
headers["Authorization"] = "Token " + self.token
return headers
def _handle_response(self, response):
if response.ok:
return response.json()
else:
return {"result": "error"}
@@ -0,0 +1,200 @@
import bpy
import json
import ifcopenshell
import ifcopenshell.util.element
from math import degrees, atan2
from blenderbim.bim.ifc import IfcStore
from .api import Api
api = Api()
class Login(bpy.types.Operator):
bl_idname = "bim.covetool_login"
bl_label = "Login to cove.tool"
def execute(self, context):
token = api.login(bpy.context.scene.CoveToolProperties.username, bpy.context.scene.CoveToolProperties.password)
if token:
bpy.context.scene.CoveToolProperties.token = token
projects = api.get_request("projects")
for project in projects:
new_project = bpy.context.scene.CoveToolProperties.projects.add()
new_project.name = project["name"]
new_project.run_set = project["run_set"][0]
new_project.url = project["url"]
else:
self.report({"ERROR"}, "Login failed :(")
return {"FINISHED"}
class RunSimpleAnalysis(bpy.types.Operator):
bl_idname = "bim.covetool_run_simple_analysis"
bl_label = "Run Simple Analysis"
def execute(self, context):
simple_analysis = bpy.context.scene.CoveToolProperties.simple_analysis
data = {
"run": bpy.context.scene.CoveToolProperties.projects[
bpy.context.scene.CoveToolProperties.active_project_index
].run_set,
"si_units": simple_analysis.si_units,
"building_height": simple_analysis.building_height,
"roof_area": simple_analysis.roof_area,
"floor_area": simple_analysis.floor_area,
"skylight_area": simple_analysis.skylight_area,
"wall_area_e": simple_analysis.wall_area_e,
"wall_area_ne": simple_analysis.wall_area_ne,
"wall_area_n": simple_analysis.wall_area_n,
"wall_area_nw": simple_analysis.wall_area_nw,
"wall_area_w": simple_analysis.wall_area_w,
"wall_area_sw": simple_analysis.wall_area_sw,
"wall_area_s": simple_analysis.wall_area_s,
"wall_area_se": simple_analysis.wall_area_se,
"window_area_e": simple_analysis.window_area_e,
"window_area_ne": simple_analysis.window_area_ne,
"window_area_n": simple_analysis.window_area_n,
"window_area_nw": simple_analysis.window_area_nw,
"window_area_w": simple_analysis.window_area_w,
"window_area_sw": simple_analysis.window_area_sw,
"window_area_s": simple_analysis.window_area_s,
"window_area_se": simple_analysis.window_area_se,
}
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"}
class RunAnalysis(bpy.types.Operator):
bl_idname = "bim.covetool_run_analysis"
bl_label = "Run Analysis"
def execute(self, context):
self.file = IfcStore.get_file()
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": self.get_rotation_angle(),
**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 get_rotation_angle(self):
if not self.file.by_type("IfcMapConversion"):
return 0
map_conversion = self.file.by_type("IfcMapConversion")[0]
rotation = -1 * degrees(
atan2(
float(map_conversion.XAxisOrdinate or 0),
float(map_conversion.XAxisAbscissa or 1),
)
)
if rotation < 0:
rotation = 360 - rotation
return rotation
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 not obj.BIMObjectProperties.ifc_definition_id:
return
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
ifc_class = element.is_a()
if "IfcSlab" in ifc_class:
return "floors"
elif "IfcRoof" in ifc_class:
return "roofs"
elif "IfcWall" in ifc_class:
if self.is_wall_internal(element):
return "interior_walls"
return "walls"
elif "IfcWindow" in ifc_class:
if self.is_window_skylight(element):
return "skylights"
return "windows"
elif "IfcShadingDevice" in ifc_class:
return "shading_devices"
def is_wall_internal(self, element):
psets = ifcopenshell.util.element.get_psets(element)
pset = psets.get("Pset_WallCommon")
if pset:
is_external = pset.get("IsExternal", None)
if is_external is not None:
return is_external
predefined_type = element.get_info().get("PredefinedType")
if predefined_type and predefined_type in ["MOVABLE", "PARTITIONING", "PLUMBINGWALL"]:
return True
def is_window_skylight(self, element):
predefined_type = element.get_info().get("PredefinedType")
return predefined_type and predefined_type.string_value == "SKYLIGHT"
@@ -0,0 +1,41 @@
import bpy.props
import bpy.types
class CoveToolProject(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(name="Name")
run_set: bpy.props.StringProperty(name="Run Set")
url: bpy.props.StringProperty(name="URL")
class CoveToolSimpleAnalysis(bpy.types.PropertyGroup):
si_units: bpy.props.BoolProperty(name="SI Units")
building_height: bpy.props.StringProperty(name="Building Height")
roof_area: bpy.props.StringProperty(name="Roof Area")
floor_area: bpy.props.StringProperty(name="Floor Area")
skylight_area: bpy.props.StringProperty(name="Skylight Area")
wall_area_e: bpy.props.StringProperty(name="Wall Area E")
wall_area_ne: bpy.props.StringProperty(name="Wall Area NE")
wall_area_n: bpy.props.StringProperty(name="Wall Area N")
wall_area_nw: bpy.props.StringProperty(name="Wall Area NW")
wall_area_w: bpy.props.StringProperty(name="Wall Area W")
wall_area_sw: bpy.props.StringProperty(name="Wall Area SW")
wall_area_s: bpy.props.StringProperty(name="Wall Area S")
wall_area_se: bpy.props.StringProperty(name="Wall Area SE")
window_area_e: bpy.props.StringProperty(name="Window Area E")
window_area_ne: bpy.props.StringProperty(name="Window Area NE")
window_area_n: bpy.props.StringProperty(name="Window Area N")
window_area_nw: bpy.props.StringProperty(name="Window Area NW")
window_area_w: bpy.props.StringProperty(name="Window Area W")
window_area_sw: bpy.props.StringProperty(name="Window Area SW")
window_area_s: bpy.props.StringProperty(name="Window Area S")
window_area_se: bpy.props.StringProperty(name="Window Area SE")
class CoveToolProperties(bpy.types.PropertyGroup):
username: bpy.props.StringProperty(name="Username")
password: bpy.props.StringProperty(name="Password")
token: bpy.props.StringProperty(name="Token")
projects: bpy.props.CollectionProperty(name="Projects", type=CoveToolProject)
active_project_index: bpy.props.IntProperty(name="Active Project Index")
simple_analysis: bpy.props.PointerProperty(type=CoveToolSimpleAnalysis)
@@ -0,0 +1,70 @@
import bpy.types
class BIM_PT_covetool(bpy.types.Panel):
bl_label = "cove.tool"
bl_idname = "BIM_PT_covetool"
bl_options = {"DEFAULT_CLOSED"}
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
props = scene.CoveToolProperties
if not props.token:
row = layout.row()
row.prop(props, "username")
row = layout.row()
row.prop(props, "password")
row = layout.row()
row.operator("bim.covetool_login")
return
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",
"wall_area_se",
"window_area_e",
"window_area_ne",
"window_area_n",
"window_area_nw",
"window_area_w",
"window_area_sw",
"window_area_s",
"window_area_se",
]
for prop_name in prop_names:
row = layout.row()
row.prop(props.simple_analysis, prop_name)
row = layout.row()
row.operator("bim.covetool_run_simple_analysis")
class BIM_UL_covetool_projects(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
ob = data
if item:
layout.prop(item, "name", text="", emboss=False)
else:
layout.label(text="", translate=False)