mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 00:59:59 +00:00
Total refactoring for CSV into a blenderBim module + use of IfcStore (#1254)
* Add new feature to Load from IFCStore in Cobie * Initial refactor for CSV to become a CSV Module * Update __init__.py * Address Dion's review Co-authored-by: Ihab El Aghoury <ihab_elaghoury@yahoo.ca> Co-authored-by: Dion Moult <dion@thinkmoult.com>
This commit is contained in:
@@ -16,6 +16,7 @@ if bpy is not None:
|
|||||||
"cobie": None,
|
"cobie": None,
|
||||||
"context": None,
|
"context": None,
|
||||||
"covetool": None,
|
"covetool": None,
|
||||||
|
"csv": None,
|
||||||
"debug": None,
|
"debug": None,
|
||||||
"geometry": None,
|
"geometry": None,
|
||||||
"model": None,
|
"model": None,
|
||||||
@@ -140,11 +141,6 @@ if bpy is not None:
|
|||||||
operator.RemovePropertyTemplate,
|
operator.RemovePropertyTemplate,
|
||||||
operator.AddSectionPlane,
|
operator.AddSectionPlane,
|
||||||
operator.RemoveSectionPlane,
|
operator.RemoveSectionPlane,
|
||||||
operator.AddCsvAttribute,
|
|
||||||
operator.RemoveCsvAttribute,
|
|
||||||
operator.ExportIfcCsv,
|
|
||||||
operator.ImportIfcCsv,
|
|
||||||
operator.EyedropIfcCsv,
|
|
||||||
operator.ReloadIfcFile,
|
operator.ReloadIfcFile,
|
||||||
operator.AddIfcFile,
|
operator.AddIfcFile,
|
||||||
operator.RemoveIfcFile,
|
operator.RemoveIfcFile,
|
||||||
@@ -255,7 +251,6 @@ if bpy is not None:
|
|||||||
ui.BIM_PT_document_information,
|
ui.BIM_PT_document_information,
|
||||||
ui.BIM_PT_constraints,
|
ui.BIM_PT_constraints,
|
||||||
ui.BIM_PT_search,
|
ui.BIM_PT_search,
|
||||||
ui.BIM_PT_ifccsv,
|
|
||||||
ui.BIM_PT_ifcclash,
|
ui.BIM_PT_ifcclash,
|
||||||
ui.BIM_PT_qa,
|
ui.BIM_PT_qa,
|
||||||
ui.BIM_PT_library,
|
ui.BIM_PT_library,
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import bpy
|
||||||
|
from . import ui, prop, operator
|
||||||
|
|
||||||
|
classes = (
|
||||||
|
operator.AddCsvAttribute,
|
||||||
|
operator.RemoveCsvAttribute,
|
||||||
|
operator.ExportIfcCsv,
|
||||||
|
operator.ImportIfcCsv,
|
||||||
|
operator.EyedropIfcCsv,
|
||||||
|
prop.CsvProperties,
|
||||||
|
ui.BIM_PT_ifccsv,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def register():
|
||||||
|
bpy.types.Scene.CsvProperties = bpy.props.PointerProperty(type=prop.CsvProperties)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
del bpy.types.Scene.CsvProperties
|
||||||
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import bpy
|
||||||
|
import ifccsv
|
||||||
|
import ifcopenshell
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import json
|
||||||
|
import webbrowser
|
||||||
|
import tempfile
|
||||||
|
from blenderbim.bim.ifc import IfcStore
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AddCsvAttribute(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.add_csv_attribute"
|
||||||
|
bl_label = "Add CSV Attribute"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
attribute = bpy.context.scene.CsvProperties.csv_attributes.add()
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
class RemoveCsvAttribute(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.remove_csv_attribute"
|
||||||
|
bl_label = "Remove CSV Attribute"
|
||||||
|
index: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
bpy.context.scene.CsvProperties.csv_attributes.remove(self.index)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
class ExportIfcCsv(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.export_ifccsv"
|
||||||
|
bl_label = "Export IFC to CSV"
|
||||||
|
filename_ext = ".csv"
|
||||||
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv")
|
||||||
|
WindowManager = context.window_manager
|
||||||
|
WindowManager.fileselect_add(self)
|
||||||
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
import ifccsv
|
||||||
|
|
||||||
|
self.filepath = bpy.path.ensure_ext(self.filepath, ".csv")
|
||||||
|
ifc_file = ifcopenshell.open(bpy.context.scene.CsvProperties.csv_ifc_file)
|
||||||
|
selector = ifcopenshell.util.selector.Selector()
|
||||||
|
results = selector.parse(ifc_file, bpy.context.scene.CsvProperties.ifc_selector)
|
||||||
|
ifc_csv = ifccsv.IfcCsv()
|
||||||
|
ifc_csv.output = self.filepath
|
||||||
|
ifc_csv.attributes = [a.name for a in bpy.context.scene.CsvProperties.csv_attributes]
|
||||||
|
ifc_csv.selector = selector
|
||||||
|
if bpy.context.scene.CsvProperties.csv_delimiter == "CUSTOM":
|
||||||
|
ifc_csv.delimiter = bpy.context.scene.CsvProperties.csv_custom_delimiter
|
||||||
|
else:
|
||||||
|
ifc_csv.delimiter = bpy.context.scene.CsvProperties.csv_delimiter
|
||||||
|
ifc_csv.export(ifc_file, results)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
class ImportIfcCsv(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.import_ifccsv"
|
||||||
|
bl_label = "Import CSV to IFC"
|
||||||
|
filename_ext = ".csv"
|
||||||
|
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv")
|
||||||
|
WindowManager = context.window_manager
|
||||||
|
WindowManager.fileselect_add(self)
|
||||||
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
import ifccsv
|
||||||
|
|
||||||
|
ifc_csv = ifccsv.IfcCsv()
|
||||||
|
ifc_csv.output = self.filepath
|
||||||
|
ifc_csv.Import(bpy.context.scene.CsvProperties.csv_ifc_file)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
class EyedropIfcCsv(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.eyedrop_ifccsv"
|
||||||
|
bl_label = "Query Selected Items"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
global_ids = []
|
||||||
|
for obj in bpy.context.selected_objects:
|
||||||
|
if hasattr(obj, "BIMObjectProperties") and obj.BIMObjectProperties.attributes.get("GlobalId"):
|
||||||
|
global_ids.append("#" + obj.BIMObjectProperties.attributes.get("GlobalId").string_value)
|
||||||
|
bpy.context.scene.CsvProperties.ifc_selector = "|".join(global_ids)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import bpy
|
||||||
|
from blenderbim.bim.prop import StrProperty
|
||||||
|
from bpy.types import PropertyGroup
|
||||||
|
from bpy.props import (
|
||||||
|
PointerProperty,
|
||||||
|
StringProperty,
|
||||||
|
EnumProperty,
|
||||||
|
BoolProperty,
|
||||||
|
IntProperty,
|
||||||
|
FloatProperty,
|
||||||
|
FloatVectorProperty,
|
||||||
|
CollectionProperty,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CsvProperties(PropertyGroup):
|
||||||
|
csv_ifc_file: StringProperty(default="", name="CSV IFC File")
|
||||||
|
ifc_selector: StringProperty(default="", name="IFC Selector")
|
||||||
|
csv_attributes: CollectionProperty(name="CSV Attributes", type=StrProperty)
|
||||||
|
csv_delimiter: EnumProperty(
|
||||||
|
items=[(";", ";", ""), (",", ",", ""), (".", ".", ""), ("CUSTOM", "Custom", ""),],
|
||||||
|
name="IFC CSV Delimiter",
|
||||||
|
default=",",
|
||||||
|
)
|
||||||
|
csv_custom_delimiter: StringProperty(default="", name="Custom Delimiter")
|
||||||
|
should_load_from_memory: BoolProperty(default=False, name="Load from Memory")
|
||||||
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
from bpy.types import Panel
|
||||||
|
from blenderbim.bim.ifc import IfcStore
|
||||||
|
|
||||||
|
|
||||||
|
class BIM_PT_ifccsv(Panel):
|
||||||
|
bl_label = "IFC CSV Import/Export"
|
||||||
|
bl_idname = "BIM_PT_ifccsv"
|
||||||
|
bl_options = {"DEFAULT_CLOSED"}
|
||||||
|
bl_space_type = "PROPERTIES"
|
||||||
|
bl_region_type = "WINDOW"
|
||||||
|
bl_context = "scene"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
scene = context.scene
|
||||||
|
props = scene.CsvProperties
|
||||||
|
|
||||||
|
if IfcStore.get_file():
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(props, "should_load_from_memory")
|
||||||
|
|
||||||
|
if not IfcStore.get_file() or not props.should_load_from_memory:
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(props, "csv_ifc_file")
|
||||||
|
row.operator("bim.import_ifccsv", icon="FILE_FOLDER", text="")
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(props, "ifc_selector")
|
||||||
|
row.operator("bim.eyedrop_ifccsv", icon="EYEDROPPER", text="")
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.label(text="Add IFC attributes to filter", icon="FILE_BLANK")
|
||||||
|
row.operator("bim.add_csv_attribute")
|
||||||
|
|
||||||
|
for index, attribute in enumerate(props.csv_attributes):
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(attribute, "name", text="")
|
||||||
|
row.operator("bim.remove_csv_attribute", icon="X", text="").index = index
|
||||||
|
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(props, "csv_delimiter")
|
||||||
|
|
||||||
|
if(props.csv_delimiter == 'CUSTOM'):
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(props, "csv_custom_delimiter")
|
||||||
|
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.operator("bim.export_ifccsv", icon="EXPORT")
|
||||||
|
row.operator("bim.import_ifccsv", icon="IMPORT")
|
||||||
|
|
||||||
@@ -2457,90 +2457,6 @@ class RemoveSectionPlane(bpy.types.Operator):
|
|||||||
bpy.ops.object.delete({"selected_objects": [bpy.context.active_object]})
|
bpy.ops.object.delete({"selected_objects": [bpy.context.active_object]})
|
||||||
|
|
||||||
|
|
||||||
class AddCsvAttribute(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.add_csv_attribute"
|
|
||||||
bl_label = "Add CSV Attribute"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
attribute = bpy.context.scene.BIMProperties.csv_attributes.add()
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class RemoveCsvAttribute(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.remove_csv_attribute"
|
|
||||||
bl_label = "Remove CSV Attribute"
|
|
||||||
index: bpy.props.IntProperty()
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
bpy.context.scene.BIMProperties.csv_attributes.remove(self.index)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class ExportIfcCsv(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.export_ifccsv"
|
|
||||||
bl_label = "Export IFC to CSV"
|
|
||||||
filename_ext = ".csv"
|
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv")
|
|
||||||
WindowManager = context.window_manager
|
|
||||||
WindowManager.fileselect_add(self)
|
|
||||||
return {"RUNNING_MODAL"}
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
import ifccsv
|
|
||||||
|
|
||||||
self.filepath = bpy.path.ensure_ext(self.filepath, ".csv")
|
|
||||||
ifc_file = ifcopenshell.open(bpy.context.scene.BIMProperties.ifc_file)
|
|
||||||
selector = ifcopenshell.util.selector.Selector()
|
|
||||||
results = selector.parse(ifc_file, bpy.context.scene.BIMProperties.ifc_selector)
|
|
||||||
ifc_csv = ifccsv.IfcCsv()
|
|
||||||
ifc_csv.output = self.filepath
|
|
||||||
ifc_csv.attributes = [a.name for a in bpy.context.scene.BIMProperties.csv_attributes]
|
|
||||||
ifc_csv.selector = selector
|
|
||||||
if bpy.context.scene.BIMProperties.csv_delimiter == "CUSTOM":
|
|
||||||
ifc_csv.delimiter = bpy.context.scene.BIMProperties.csv_custom_delimiter
|
|
||||||
else:
|
|
||||||
ifc_csv.delimiter = bpy.context.scene.BIMProperties.csv_delimiter
|
|
||||||
ifc_csv.export(ifc_file, results)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class ImportIfcCsv(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.import_ifccsv"
|
|
||||||
bl_label = "Import CSV to IFC"
|
|
||||||
filename_ext = ".csv"
|
|
||||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".csv")
|
|
||||||
WindowManager = context.window_manager
|
|
||||||
WindowManager.fileselect_add(self)
|
|
||||||
return {"RUNNING_MODAL"}
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
import ifccsv
|
|
||||||
|
|
||||||
ifc_csv = ifccsv.IfcCsv()
|
|
||||||
ifc_csv.output = self.filepath
|
|
||||||
ifc_csv.Import(bpy.context.scene.BIMProperties.ifc_file)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class EyedropIfcCsv(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.eyedrop_ifccsv"
|
|
||||||
bl_label = "Query Selected Items"
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
global_ids = []
|
|
||||||
for obj in bpy.context.selected_objects:
|
|
||||||
if hasattr(obj, "BIMObjectProperties") and obj.BIMObjectProperties.attributes.get("GlobalId"):
|
|
||||||
global_ids.append("#" + obj.BIMObjectProperties.attributes.get("GlobalId").string_value)
|
|
||||||
bpy.context.scene.BIMProperties.ifc_selector = "|".join(global_ids)
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class ReloadIfcFile(bpy.types.Operator):
|
class ReloadIfcFile(bpy.types.Operator):
|
||||||
bl_idname = "bim.reload_ifc_file"
|
bl_idname = "bim.reload_ifc_file"
|
||||||
bl_label = "Reload IFC File"
|
bl_label = "Reload IFC File"
|
||||||
|
|||||||
@@ -1322,13 +1322,6 @@ class BIMProperties(PropertyGroup):
|
|||||||
name="Import Filter",
|
name="Import Filter",
|
||||||
)
|
)
|
||||||
ifc_selector: StringProperty(default="", name="IFC Selector")
|
ifc_selector: StringProperty(default="", name="IFC Selector")
|
||||||
csv_attributes: CollectionProperty(name="CSV Attributes", type=StrProperty)
|
|
||||||
csv_delimiter: EnumProperty(
|
|
||||||
items=[(";", ";", ""), (",", ",", ""), (".", ".", ""), ("CUSTOM", "Custom", ""),],
|
|
||||||
name="IFC CSV Delimiter",
|
|
||||||
default=";",
|
|
||||||
)
|
|
||||||
csv_custom_delimiter: StringProperty(default="", name="Custom Delimiter")
|
|
||||||
document_information: CollectionProperty(name="Document Information", type=DocumentInformation)
|
document_information: CollectionProperty(name="Document Information", type=DocumentInformation)
|
||||||
active_document_information_index: IntProperty(name="Active Document Information Index")
|
active_document_information_index: IntProperty(name="Active Document Information Index")
|
||||||
document_references: CollectionProperty(name="Document References", type=DocumentReference)
|
document_references: CollectionProperty(name="Document References", type=DocumentReference)
|
||||||
|
|||||||
@@ -1069,42 +1069,6 @@ class BIM_PT_search(Panel):
|
|||||||
row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA")
|
row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA")
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_ifccsv(Panel):
|
|
||||||
bl_label = "IFC CSV Import/Export"
|
|
||||||
bl_idname = "BIM_PT_ifccsv"
|
|
||||||
bl_options = {"DEFAULT_CLOSED"}
|
|
||||||
bl_space_type = "PROPERTIES"
|
|
||||||
bl_region_type = "WINDOW"
|
|
||||||
bl_context = "scene"
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
|
|
||||||
scene = context.scene
|
|
||||||
props = scene.BIMProperties
|
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.prop(props, "ifc_selector")
|
|
||||||
row.operator("bim.eyedrop_ifccsv", icon="EYEDROPPER", text="")
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.operator("bim.add_csv_attribute")
|
|
||||||
|
|
||||||
for index, attribute in enumerate(props.csv_attributes):
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.prop(attribute, "name", text="")
|
|
||||||
row.operator("bim.remove_csv_attribute", icon="X", text="").index = index
|
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.prop(props, "csv_delimiter")
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.prop(props, "csv_custom_delimiter")
|
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.operator("bim.export_ifccsv", icon="EXPORT")
|
|
||||||
row.operator("bim.import_ifccsv", icon="IMPORT")
|
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_qa(Panel):
|
class BIM_PT_qa(Panel):
|
||||||
bl_label = "BIMTester Quality Auditing"
|
bl_label = "BIMTester Quality Auditing"
|
||||||
bl_idname = "BIM_PT_qa"
|
bl_idname = "BIM_PT_qa"
|
||||||
|
|||||||
Reference in New Issue
Block a user