mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Purge all Python test code
This commit is contained in:
@@ -909,8 +909,6 @@ if(BUILD_IFCGEOM)
|
||||
file(GLOB SCHEMA_AGNOSTIC_CPP_FILES ../src/ifcgeom_schema_agnostic/*.cpp)
|
||||
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES})
|
||||
|
||||
include_directories(/home/dion/.config/blender/4.0/scripts/addons/blenderbim/libs/site/packages/numpy/core/include)
|
||||
|
||||
add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES})
|
||||
set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||
|
||||
|
||||
@@ -49,13 +49,6 @@ classes = (
|
||||
operator.UnloadLink,
|
||||
operator.UnloadProject,
|
||||
operator.ReloadLink,
|
||||
operator.xxx,
|
||||
operator.zzz,
|
||||
operator.zxc,
|
||||
operator.aaa,
|
||||
operator.asdfasdf,
|
||||
operator.qwerqwer,
|
||||
operator.qwerqwer2,
|
||||
operator.LoadLinkedProject,
|
||||
operator.QueryLinkedElement,
|
||||
operator.EnableCulling,
|
||||
|
||||
@@ -1173,412 +1173,6 @@ class ImportIFC(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class xxx(bpy.types.Operator):
|
||||
bl_idname = "bim.xxx"
|
||||
bl_label = "Load IFC no chunking"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
import time
|
||||
import multiprocessing
|
||||
import ifcopenshell.geom
|
||||
import numpy as np
|
||||
from mathutils import Matrix
|
||||
import resource
|
||||
|
||||
mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
|
||||
start = time.time()
|
||||
|
||||
collection = bpy.data.collections.new("Project")
|
||||
# ifc_file = ifcopenshell.open('/home/dion/test.ifc')
|
||||
# ifc_file = ifcopenshell.open('/home/dion/drive/ifcs/racbasicsampleproject.ifc')
|
||||
ifc_file = ifcopenshell.open("/home/dion/drive/ifcs/TXG_sample_project-fixed-IFC4.ifc")
|
||||
|
||||
settings = ifcopenshell.geom.settings()
|
||||
iterator = ifcopenshell.geom.iterator(settings, ifc_file, multiprocessing.cpu_count())
|
||||
meshes = {}
|
||||
blender_mats = {}
|
||||
if iterator.initialize():
|
||||
while True:
|
||||
shape = iterator.get()
|
||||
element = ifc_file.by_id(shape.id)
|
||||
matrix = shape.transformation.matrix.data
|
||||
faces = shape.geometry.faces
|
||||
verts = shape.geometry.verts
|
||||
materials = shape.geometry.materials
|
||||
material_ids = shape.geometry.material_ids
|
||||
|
||||
m = shape.transformation.matrix.data
|
||||
mat = np.array(
|
||||
([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1])
|
||||
)
|
||||
|
||||
mesh = meshes.get(shape.geometry.id, None)
|
||||
if not mesh:
|
||||
mesh = bpy.data.meshes.new("Mesh")
|
||||
|
||||
material_to_slot = {}
|
||||
max_slot_index = 0
|
||||
|
||||
for i, material in enumerate(materials):
|
||||
alpha = 1.0
|
||||
if material.has_transparency and material.transparency > 0:
|
||||
alpha = 1.0 - material.transparency
|
||||
diffuse = material.diffuse + (alpha,)
|
||||
material_name = f"{diffuse[0]}-{diffuse[1]}-{diffuse[2]}-{diffuse[3]}"
|
||||
blender_mat = blender_mats.get(material_name, None)
|
||||
if not blender_mat:
|
||||
blender_mat = bpy.data.materials.new(material_name)
|
||||
blender_mat.diffuse_color = diffuse
|
||||
blender_mats[material_name] = blender_mat
|
||||
slot_index = mesh.materials.find(material.name)
|
||||
if slot_index == -1:
|
||||
mesh.materials.append(blender_mat)
|
||||
slot_index = max_slot_index
|
||||
max_slot_index += 1
|
||||
material_to_slot[i] = slot_index
|
||||
|
||||
material_index = [(material_to_slot[i] if i != -1 else 0) for i in material_ids]
|
||||
|
||||
num_vertices = len(verts) // 3
|
||||
total_faces = len(faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(faces)
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
mesh.polygons.foreach_set("material_index", material_index)
|
||||
mesh.update()
|
||||
|
||||
meshes[shape.geometry.id] = mesh
|
||||
|
||||
obj = bpy.data.objects.new(tool.Loader.get_name(element), mesh)
|
||||
obj.matrix_world = Matrix(mat.tolist())
|
||||
collection.objects.link(obj)
|
||||
|
||||
if not iterator.next():
|
||||
break
|
||||
|
||||
bpy.context.scene.collection.children.link(collection)
|
||||
print("Finished", time.time() - start)
|
||||
newmem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
|
||||
print("Mem", newmem - mem)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class zzz(bpy.types.Operator):
|
||||
bl_idname = "bim.zzz"
|
||||
bl_label = "Load H5 no chunking"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
import uuid
|
||||
import h5py
|
||||
import multiprocessing
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
import numpy as np
|
||||
import time
|
||||
from mathutils import Matrix
|
||||
import resource
|
||||
|
||||
mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
|
||||
start = time.time()
|
||||
|
||||
collection = bpy.data.collections.new("Project")
|
||||
model = h5py.File("/home/dion/test3.h5", "r")
|
||||
# model = h5py.File('/home/dion/cpp.h5', 'r')
|
||||
# model = h5py.File('/home/dion/test5.h5', 'r')
|
||||
# model = h5py.File('/home/dion/test4.h5', 'r')
|
||||
# model = h5py.File('/home/dion/filename.h5', 'r')
|
||||
|
||||
materials = {}
|
||||
for i, rgb in enumerate(model["materials"]):
|
||||
blender_mat = bpy.data.materials.new(str(i))
|
||||
blender_mat.diffuse_color = rgb[()].tolist()
|
||||
materials[i] = blender_mat
|
||||
|
||||
meshes = {}
|
||||
for shape_id, shape in model["shapes"].items():
|
||||
mesh = bpy.data.meshes.new(shape_id)
|
||||
meshes[int(shape_id)] = mesh
|
||||
|
||||
for material in shape["materials"]:
|
||||
mesh.materials.append(materials[material])
|
||||
|
||||
verts = shape["verts"][()].tolist()
|
||||
faces = shape["faces"][()].tolist()
|
||||
|
||||
num_vertices = len(verts) // 3
|
||||
total_faces = len(faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(faces)
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
|
||||
if "material_ids" in shape:
|
||||
mesh.polygons.foreach_set("material_index", shape["material_ids"][()].tolist())
|
||||
|
||||
mesh.update()
|
||||
|
||||
for i, global_id in enumerate(model["element_global_ids"]):
|
||||
global_id = str(uuid.UUID(bytes=bytes(global_id)))
|
||||
obj = bpy.data.objects.new(global_id, meshes[model["element_shape_ids"][i]])
|
||||
m = model["element_matrices"][i]
|
||||
mat = np.array(
|
||||
([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1])
|
||||
)
|
||||
obj.matrix_world = Matrix(mat.tolist())
|
||||
collection.objects.link(obj)
|
||||
|
||||
bpy.context.scene.collection.children.link(collection)
|
||||
print("Finished", time.time() - start)
|
||||
newmem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
|
||||
print("Mem", newmem - mem)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class zxc(bpy.types.Operator):
|
||||
bl_idname = "bim.zxc"
|
||||
bl_label = "Load H5 Python chunking"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
import uuid
|
||||
import h5py
|
||||
import multiprocessing
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
import time
|
||||
from mathutils import Matrix
|
||||
import resource
|
||||
|
||||
mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
|
||||
start = time.time()
|
||||
|
||||
self.collection = bpy.data.collections.new("Project")
|
||||
model = h5py.File("/home/dion/test3.h5", "r")
|
||||
# model = h5py.File('/home/dion/test5.h5', 'r')
|
||||
print("Opened", time.time() - start)
|
||||
|
||||
materials = {}
|
||||
for i, rgb in enumerate(model["materials"]):
|
||||
blender_mat = bpy.data.materials.new(str(i))
|
||||
blender_mat.diffuse_color = rgb[()].tolist()
|
||||
materials[i] = blender_mat
|
||||
|
||||
print("Materials", time.time() - start)
|
||||
|
||||
shapes = {}
|
||||
for shape_id, shape in model["shapes"].items():
|
||||
verts = np.array(shape["verts"][()].tolist())
|
||||
faces = shape["faces"][()].tolist()
|
||||
|
||||
shapes[int(shape_id)] = {
|
||||
"verts": verts,
|
||||
"faces": faces,
|
||||
"materials": [materials[m] for m in shape["materials"]],
|
||||
"material_ids": shape["material_ids"][()].tolist() if "material_ids" in shape else None,
|
||||
}
|
||||
|
||||
print("Shapes", time.time() - start)
|
||||
|
||||
chunk_size = 10000
|
||||
|
||||
offset = 0
|
||||
material_offset = 0
|
||||
chunked_verts = []
|
||||
chunked_faces = []
|
||||
chunked_materials = []
|
||||
chunked_material_ids = []
|
||||
|
||||
for i, global_id in enumerate(model["element_global_ids"]):
|
||||
global_id = str(uuid.UUID(bytes=bytes(global_id)))
|
||||
m = model["element_matrices"][i]
|
||||
mat = np.array(
|
||||
([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1])
|
||||
)
|
||||
|
||||
shape = shapes[model["element_shape_ids"][i]]
|
||||
verts = self.apply_matrix_to_flat_list(shape["verts"], mat)
|
||||
faces = [f + offset for f in shape["faces"]]
|
||||
|
||||
chunked_verts.extend(verts)
|
||||
chunked_faces.extend(faces)
|
||||
|
||||
material_map = {}
|
||||
for material_index, material in enumerate(shape["materials"]):
|
||||
try:
|
||||
chunked_index = chunked_materials.index(material)
|
||||
except:
|
||||
chunked_index = len(chunked_materials)
|
||||
chunked_materials.append(material)
|
||||
material_map[material_index] = chunked_index
|
||||
|
||||
if shape["material_ids"] is None:
|
||||
chunked_material_ids.extend([list(material_map.values())[0]] * (len(faces) // 3))
|
||||
else:
|
||||
chunked_material_ids.extend([material_map[m] for m in shape["material_ids"]])
|
||||
|
||||
offset += len(verts) // 3
|
||||
material_offset += len(shape["materials"])
|
||||
|
||||
if offset > chunk_size:
|
||||
print("Chunk at", i)
|
||||
self.create_object(chunked_verts, chunked_faces, chunked_materials, chunked_material_ids)
|
||||
chunked_verts = []
|
||||
chunked_faces = []
|
||||
chunked_materials = []
|
||||
chunked_material_ids = []
|
||||
offset = 0
|
||||
material_offset = 0
|
||||
|
||||
if offset:
|
||||
self.create_object(chunked_verts, chunked_faces, chunked_materials, chunked_material_ids)
|
||||
|
||||
bpy.context.scene.collection.children.link(self.collection)
|
||||
print("Finished", time.time() - start)
|
||||
newmem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
|
||||
print("Mem", newmem - mem)
|
||||
return {"FINISHED"}
|
||||
|
||||
def apply_matrix_to_flat_list(self, flat_list, matrix):
|
||||
# Convert the flat list to a 2D array with 3 columns (x, y, z)
|
||||
vertices = np.array(flat_list).reshape(-1, 3)
|
||||
# Add a column of ones for homogeneous coordinates (x, y, z, 1)
|
||||
vertices = np.hstack([vertices, np.ones((vertices.shape[0], 1))])
|
||||
# Apply the matrix transformation
|
||||
transformed_vertices = np.dot(vertices, matrix.T)
|
||||
# Discard the homogeneous coordinate and flatten the array
|
||||
return transformed_vertices[:, :3].flatten()
|
||||
|
||||
def create_object(self, verts, faces, materials, material_ids):
|
||||
num_vertices = len(verts) // 3
|
||||
total_faces = len(faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(faces)
|
||||
|
||||
mesh = bpy.data.meshes.new("Mesh")
|
||||
|
||||
for material in materials:
|
||||
mesh.materials.append(material)
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
|
||||
if material_ids:
|
||||
mesh.polygons.foreach_set("material_index", material_ids)
|
||||
|
||||
mesh.update()
|
||||
|
||||
obj = bpy.data.objects.new("Blah", mesh)
|
||||
self.collection.objects.link(obj)
|
||||
|
||||
|
||||
class aaa(bpy.types.Operator):
|
||||
bl_idname = "bim.aaa"
|
||||
bl_label = "Load H5 C++ chunking"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
import uuid
|
||||
import h5py
|
||||
import multiprocessing
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
import time
|
||||
from mathutils import Matrix
|
||||
import resource
|
||||
|
||||
mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
|
||||
start = time.time()
|
||||
|
||||
tree = ifcopenshell.geom.tree()
|
||||
x = tree.load_h5()
|
||||
self.materials = {}
|
||||
for i, m in enumerate(x.materials):
|
||||
blender_mat = bpy.data.materials.new(str(i))
|
||||
blender_mat.diffuse_color = m
|
||||
self.materials[i] = blender_mat
|
||||
|
||||
self.collection = bpy.data.collections.new("Project")
|
||||
|
||||
for e in x.elements:
|
||||
# <ifcopenshell.ifcopenshell_wrapper.FloatVector; proxy of <Swig Object of type 'std::vector< float > *' at 0x7f0f871a8ff1> >
|
||||
# <class 'ifcopenshell.ifcopenshell_wrapper.FloatVector'>
|
||||
# e.get_verts()
|
||||
# e.get_verts()
|
||||
# e.get_faces()
|
||||
# self.create_object(e.verts, e.faces, e.get_materials(), e.get_material_ids()) # 14.7
|
||||
# self.create_object(list(e.verts), list(e.faces), e.get_materials(), e.get_material_ids()) # 8.9
|
||||
o = self.create_object(e.get_verts(), e.get_faces(), e.get_materials(), e.get_material_ids()) # 6.5
|
||||
o["guids"] = [ifcopenshell.guid.compress(g) for g in list(e.guids)]
|
||||
o["guid_ids"] = list(e.guid_ids)
|
||||
|
||||
bpy.context.scene.collection.children.link(self.collection)
|
||||
print("Finished", time.time() - start)
|
||||
newmem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
|
||||
print("Mem", newmem - mem)
|
||||
return {"FINISHED"}
|
||||
|
||||
def create_object(self, verts, faces, materials, material_ids):
|
||||
num_vertices = len(verts) // 3
|
||||
total_faces = len(faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(faces)
|
||||
|
||||
mesh = bpy.data.meshes.new("Mesh")
|
||||
|
||||
for material in materials:
|
||||
mesh.materials.append(self.materials[material])
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
|
||||
if material_ids.size > 0:
|
||||
mesh.polygons.foreach_set("material_index", material_ids)
|
||||
|
||||
mesh.update()
|
||||
|
||||
obj = bpy.data.objects.new("Blah", mesh)
|
||||
self.collection.objects.link(obj)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
class LoadLinkedProject(bpy.types.Operator):
|
||||
bl_idname = "bim.load_linked_project"
|
||||
bl_label = "Load a project for viewing only."
|
||||
@@ -2247,8 +1841,6 @@ class CreateClippingPlane(bpy.types.Operator):
|
||||
self.report({"INFO"}, "No object found.")
|
||||
return {"FINISHED"}
|
||||
|
||||
print(hit, location, normal, face_index, obj, matrix)
|
||||
|
||||
vertices = [(-0.5, -0.5, 0), (0.5, -0.5, 0), (0.5, 0.5, 0), (-0.5, 0.5, 0)]
|
||||
|
||||
faces = [(0, 1, 2, 3)]
|
||||
@@ -2284,498 +1876,3 @@ class CreateClippingPlane(bpy.types.Operator):
|
||||
self.mouse_x = event.mouse_region_x
|
||||
self.mouse_y = event.mouse_region_y
|
||||
return self.execute(context)
|
||||
|
||||
|
||||
class asdfasdf(bpy.types.Operator):
|
||||
bl_idname = "bim.asdfasdf"
|
||||
bl_label = "Load IFC C++ chunking"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
import ifcpatch
|
||||
import multiprocessing
|
||||
import ifcopenshell.geom
|
||||
|
||||
start = time.time()
|
||||
|
||||
# self.filepath = "/home/dion/drive/ifcs/racbasicsampleproject.ifc"
|
||||
self.filepath = "/home/dion/drive/ifcs/TXG_sample_project-fixed-IFC4.ifc"
|
||||
# self.filepath = "/home/dion/tmp/petrubug/F-ELECT.ifc"
|
||||
print("doing", self.filepath)
|
||||
|
||||
self.collection = bpy.data.collections.new("IfcProject/" + os.path.basename(self.filepath))
|
||||
self.file = ifcopenshell.open(self.filepath)
|
||||
# self.file = ifcopenshell.open('/home/dion/test.ifc')
|
||||
# self.file = ifcopenshell.open('/home/dion/drive/ifcs/TXG_sample_project-fixed-IFC4.ifc')
|
||||
# self.file = ifcopenshell.open("/home/dion/tmp/petrubug/F-ELECT.ifc")
|
||||
print("Finished opening")
|
||||
start = time.time()
|
||||
|
||||
logger = logging.getLogger("ImportIFC")
|
||||
ifc_import_settings = import_ifc.IfcImportSettings.factory(context, IfcStore.path, logger)
|
||||
ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
|
||||
ifc_importer.file = self.file
|
||||
ifc_importer.process_context_filter()
|
||||
|
||||
self.elements = set(self.file.by_type("IfcElement"))
|
||||
if self.file.schema in ("IFC2X3", "IFC4"):
|
||||
self.elements |= set(self.file.by_type("IfcProxy"))
|
||||
self.elements |= set(self.file.by_type("IfcSite"))
|
||||
self.elements -= set(self.file.by_type("IfcFeatureElement"))
|
||||
self.elements = list(self.elements)
|
||||
|
||||
for settings in ifc_importer.context_settings:
|
||||
iterator = ifcopenshell.geom.iterator(
|
||||
settings, self.file, multiprocessing.cpu_count(), include=self.elements
|
||||
)
|
||||
self.meshes = {}
|
||||
self.blender_mats = {}
|
||||
|
||||
total_materials = 0
|
||||
self.materials = []
|
||||
|
||||
ci = 0
|
||||
if iterator.initialize():
|
||||
while True:
|
||||
shape = iterator.get()
|
||||
if iterator.process_chunk():
|
||||
has_processed_chunk = True
|
||||
ci += 1
|
||||
if ci % 50 == 0:
|
||||
print("Doing chunk", ci)
|
||||
chunk = iterator.get_chunk()
|
||||
|
||||
for colour in chunk.colours:
|
||||
blender_mat = bpy.data.materials.new(str(total_materials))
|
||||
blender_mat.diffuse_color = list(colour)
|
||||
self.materials.append(blender_mat)
|
||||
total_materials += 1
|
||||
self.create_object(chunk)
|
||||
|
||||
if not iterator.next():
|
||||
if not has_processed_chunk:
|
||||
# The left over chunk
|
||||
chunk = iterator.get_chunk()
|
||||
for colour in chunk.colours:
|
||||
blender_mat = bpy.data.materials.new(str(total_materials))
|
||||
blender_mat.diffuse_color = list(colour)
|
||||
self.materials.append(blender_mat)
|
||||
total_materials += 1
|
||||
self.create_object(chunk)
|
||||
break
|
||||
|
||||
bpy.context.scene.collection.children.link(self.collection)
|
||||
print("Finished", time.time() - start)
|
||||
break
|
||||
return {"FINISHED"}
|
||||
|
||||
def create_object(self, chunk):
|
||||
verts = chunk.get_verts()
|
||||
faces = chunk.get_faces()
|
||||
materials = chunk.get_materials()
|
||||
material_ids = chunk.get_material_ids()
|
||||
|
||||
num_vertices = len(verts) // 3
|
||||
if not num_vertices:
|
||||
return
|
||||
total_faces = len(faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(faces)
|
||||
|
||||
mesh = bpy.data.meshes.new("Mesh")
|
||||
|
||||
for material in materials:
|
||||
mesh.materials.append(self.materials[material])
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
|
||||
if material_ids.size > 0:
|
||||
mesh.polygons.foreach_set("material_index", material_ids)
|
||||
|
||||
mesh.update()
|
||||
|
||||
obj = bpy.data.objects.new("Chunk", mesh)
|
||||
obj["guids"] = list(chunk.guids)
|
||||
obj["guid_ids"] = list(chunk.guid_ids)
|
||||
|
||||
self.collection.objects.link(obj)
|
||||
|
||||
|
||||
class qwerqwer(bpy.types.Operator):
|
||||
bl_idname = "bim.qwerqwer"
|
||||
bl_label = "Load IFC Numpy chunking"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
import ifcpatch
|
||||
import multiprocessing
|
||||
import ifcopenshell.geom
|
||||
|
||||
start = time.time()
|
||||
|
||||
# self.filepath = "/home/dion/drive/ifcs/racbasicsampleproject.ifc"
|
||||
# self.filepath = '/home/dion/drive/ifcs/TXG_sample_project-fixed-IFC4.ifc'
|
||||
self.filepath = "/home/dion/tmp/petrubug/F-ELECT.ifc"
|
||||
print("doing", self.filepath)
|
||||
|
||||
self.collection = bpy.data.collections.new("IfcProject/" + os.path.basename(self.filepath))
|
||||
self.file = ifcopenshell.open(self.filepath)
|
||||
# self.file = ifcopenshell.open('/home/dion/test.ifc')
|
||||
# self.file = ifcopenshell.open('/home/dion/drive/ifcs/TXG_sample_project-fixed-IFC4.ifc')
|
||||
# self.file = ifcopenshell.open("/home/dion/tmp/petrubug/F-ELECT.ifc")
|
||||
print("Finished opening")
|
||||
start = time.time()
|
||||
|
||||
logger = logging.getLogger("ImportIFC")
|
||||
ifc_import_settings = import_ifc.IfcImportSettings.factory(context, IfcStore.path, logger)
|
||||
ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
|
||||
ifc_importer.file = self.file
|
||||
ifc_importer.process_context_filter()
|
||||
|
||||
self.elements = set(self.file.by_type("IfcElement"))
|
||||
if self.file.schema in ("IFC2X3", "IFC4"):
|
||||
self.elements |= set(self.file.by_type("IfcProxy"))
|
||||
self.elements |= set(self.file.by_type("IfcSite"))
|
||||
self.elements -= set(self.file.by_type("IfcFeatureElement"))
|
||||
self.elements = list(self.elements)
|
||||
|
||||
for settings in ifc_importer.context_settings:
|
||||
iterator = ifcopenshell.geom.iterator(
|
||||
settings, self.file, multiprocessing.cpu_count(), include=self.elements
|
||||
)
|
||||
|
||||
default_mat = np.array([[1, 1, 1, 1]], dtype=np.float32)
|
||||
|
||||
self.meshes = {}
|
||||
blender_mats = {}
|
||||
|
||||
chunked_verts = []
|
||||
chunked_faces = []
|
||||
chunked_materials = []
|
||||
chunked_material_ids = []
|
||||
material_offset = 0
|
||||
max_slot_index = 0
|
||||
chunk_size = 10000
|
||||
r4 = np.array([[0, 0, 0, 1]])
|
||||
offset = 0
|
||||
|
||||
ci = 0
|
||||
if iterator.initialize():
|
||||
while True:
|
||||
shape = iterator.get()
|
||||
|
||||
has_processed_chunk = False
|
||||
|
||||
ms = np.vstack([default_mat, np.frombuffer(shape.geometry.colors_buffer).reshape((-1, 4))])
|
||||
mi = np.frombuffer(shape.geometry.material_ids_buffer, dtype=np.int32)
|
||||
chunked_materials.append(ms)
|
||||
chunked_material_ids.append(mi + material_offset + 1)
|
||||
material_offset += len(ms)
|
||||
|
||||
M4 = np.frombuffer(shape.transformation_buffer).reshape((4, 3))
|
||||
M4 = np.concatenate((M4.T, r4))
|
||||
vs = np.frombuffer(shape.geometry.verts_buffer).reshape((-1, 3))
|
||||
vs = np.hstack((vs, np.ones((len(vs), 1))))
|
||||
vs = (np.asmatrix(M4) * np.asmatrix(vs).T).T.A
|
||||
vs = vs[:, :3].flatten()
|
||||
fs = np.frombuffer(shape.geometry.faces_buffer, dtype=np.int32)
|
||||
chunked_verts.append(vs)
|
||||
chunked_faces.append(fs + offset)
|
||||
offset += len(vs) // 3
|
||||
|
||||
if offset > chunk_size:
|
||||
has_processed_chunk = True
|
||||
|
||||
mats = np.concatenate(chunked_materials)
|
||||
midx = np.concatenate(chunked_material_ids)
|
||||
mats, mapping = np.unique(mats, axis=0, return_inverse=True)
|
||||
midx = mapping[midx]
|
||||
|
||||
mat_results = []
|
||||
for mat in mats:
|
||||
mat = tuple(mat)
|
||||
blender_mat = blender_mats.get(mat, None)
|
||||
if not blender_mat:
|
||||
blender_mat = bpy.data.materials.new("Chunk")
|
||||
blender_mat.diffuse_color = mat
|
||||
blender_mats[mat] = blender_mat
|
||||
mat_results.append(blender_mat)
|
||||
|
||||
self.create_object(
|
||||
np.concatenate(chunked_verts), np.concatenate(chunked_faces), mat_results, midx
|
||||
)
|
||||
chunked_verts = []
|
||||
chunked_faces = []
|
||||
chunked_materials = []
|
||||
chunked_material_ids = []
|
||||
material_offset = 0
|
||||
max_slot_index = 0
|
||||
offset = 0
|
||||
pass
|
||||
|
||||
if not iterator.next():
|
||||
if not has_processed_chunk:
|
||||
mats = np.concatenate(chunked_materials)
|
||||
midx = np.concatenate(chunked_material_ids)
|
||||
mats, mapping = np.unique(mats, axis=0, return_inverse=True)
|
||||
midx = mapping[midx]
|
||||
|
||||
mat_results = []
|
||||
for mat in mats:
|
||||
mat = tuple(mat)
|
||||
blender_mat = blender_mats.get(mat, None)
|
||||
if not blender_mat:
|
||||
blender_mat = bpy.data.materials.new("Chunk")
|
||||
blender_mat.diffuse_color = mat
|
||||
blender_mats[mat] = blender_mat
|
||||
mat_results.append(blender_mat)
|
||||
|
||||
# The left over chunk
|
||||
self.create_object(
|
||||
np.concatenate(chunked_verts), np.concatenate(chunked_faces), mat_results, midx
|
||||
)
|
||||
break
|
||||
|
||||
bpy.context.scene.collection.children.link(self.collection)
|
||||
print("Finished", time.time() - start)
|
||||
break
|
||||
return {"FINISHED"}
|
||||
|
||||
def create_object(self, verts, faces, materials, material_ids):
|
||||
num_vertices = len(verts) // 3
|
||||
if not num_vertices:
|
||||
return
|
||||
total_faces = len(faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(faces)
|
||||
|
||||
mesh = bpy.data.meshes.new("Mesh")
|
||||
|
||||
for material in materials:
|
||||
mesh.materials.append(material)
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
|
||||
if materials:
|
||||
mesh.polygons.foreach_set("material_index", material_ids)
|
||||
|
||||
mesh.update()
|
||||
|
||||
obj = bpy.data.objects.new("Chunk", mesh)
|
||||
|
||||
self.collection.objects.link(obj)
|
||||
|
||||
|
||||
class qwerqwer2(bpy.types.Operator):
|
||||
bl_idname = "bim.qwerqwer2"
|
||||
bl_label = "Load IFC Python chunking"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
import ifcpatch
|
||||
import multiprocessing
|
||||
import ifcopenshell.geom
|
||||
|
||||
start = time.time()
|
||||
|
||||
# self.filepath = "/home/dion/drive/ifcs/racbasicsampleproject.ifc"
|
||||
self.filepath = "/home/dion/drive/ifcs/TXG_sample_project-fixed-IFC4.ifc"
|
||||
# self.filepath = "/home/dion/tmp/petrubug/F-ELECT.ifc"
|
||||
print("doing", self.filepath)
|
||||
|
||||
self.collection = bpy.data.collections.new("IfcProject/" + os.path.basename(self.filepath))
|
||||
self.file = ifcopenshell.open(self.filepath)
|
||||
# self.file = ifcopenshell.open('/home/dion/test.ifc')
|
||||
# self.file = ifcopenshell.open('/home/dion/drive/ifcs/TXG_sample_project-fixed-IFC4.ifc')
|
||||
# self.file = ifcopenshell.open("/home/dion/tmp/petrubug/F-ELECT.ifc")
|
||||
print("Finished opening")
|
||||
start = time.time()
|
||||
|
||||
logger = logging.getLogger("ImportIFC")
|
||||
ifc_import_settings = import_ifc.IfcImportSettings.factory(context, IfcStore.path, logger)
|
||||
ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
|
||||
ifc_importer.file = self.file
|
||||
ifc_importer.process_context_filter()
|
||||
|
||||
self.elements = set(self.file.by_type("IfcElement"))
|
||||
if self.file.schema in ("IFC2X3", "IFC4"):
|
||||
self.elements |= set(self.file.by_type("IfcProxy"))
|
||||
self.elements |= set(self.file.by_type("IfcSite"))
|
||||
self.elements -= set(self.file.by_type("IfcFeatureElement"))
|
||||
self.elements = list(self.elements)
|
||||
|
||||
for settings in ifc_importer.context_settings:
|
||||
iterator = ifcopenshell.geom.iterator(
|
||||
settings, self.file, multiprocessing.cpu_count(), include=self.elements
|
||||
)
|
||||
|
||||
default_mat = bpy.data.materials.new("Default")
|
||||
default_mat.diffuse_color = (1, 1, 1, 1)
|
||||
|
||||
self.meshes = {}
|
||||
blender_mats = {}
|
||||
|
||||
total_materials = 0
|
||||
self.materials = []
|
||||
|
||||
chunked_verts = []
|
||||
chunked_faces = []
|
||||
chunked_materials = []
|
||||
chunked_material_ids = []
|
||||
max_slot_index = 0
|
||||
chunk_size = 10000
|
||||
r4 = np.array([[0, 0, 0, 1]])
|
||||
offset = 0
|
||||
|
||||
ci = 0
|
||||
if iterator.initialize():
|
||||
while True:
|
||||
shape = iterator.get()
|
||||
|
||||
materials = shape.geometry.materials
|
||||
material_ids = shape.geometry.material_ids
|
||||
# material_ids = np.frombuffer(shape.geometry.material_ids_buffer)
|
||||
|
||||
material_to_slot = {}
|
||||
|
||||
for i, material in enumerate(materials):
|
||||
alpha = 1.0
|
||||
if material.has_transparency and material.transparency > 0:
|
||||
alpha = 1.0 - material.transparency
|
||||
diffuse = material.diffuse + (alpha,)
|
||||
material_name = f"{diffuse[0]}-{diffuse[1]}-{diffuse[2]}-{diffuse[3]}"
|
||||
blender_mat = blender_mats.get(material_name, None)
|
||||
if not blender_mat:
|
||||
blender_mat = bpy.data.materials.new(material_name)
|
||||
blender_mat.diffuse_color = diffuse
|
||||
blender_mats[material_name] = blender_mat
|
||||
try:
|
||||
slot_index = chunked_materials.index(blender_mat)
|
||||
except ValueError:
|
||||
chunked_materials.append(blender_mat)
|
||||
slot_index = max_slot_index
|
||||
max_slot_index += 1
|
||||
material_to_slot[i] = slot_index
|
||||
|
||||
if not materials:
|
||||
try:
|
||||
slot_index = chunked_materials.index(default_mat)
|
||||
except ValueError:
|
||||
chunked_materials.append(default_mat)
|
||||
slot_index = max_slot_index
|
||||
max_slot_index += 1
|
||||
material_to_slot[-1] = slot_index
|
||||
|
||||
# Numpy alternative
|
||||
"""
|
||||
# Convert material_to_slot dictionary to a NumPy array
|
||||
max_material_id = max(material_to_slot.keys())
|
||||
material_to_slot_array = np.zeros(max_material_id + 1, dtype=int)
|
||||
for material_id, slot in material_to_slot.items():
|
||||
material_to_slot_array[material_id] = slot
|
||||
|
||||
# Efficiently map material_ids to slots using NumPy
|
||||
material_ids = np.frombuffer(shape.geometry.material_ids_buffer, dtype=np.int32) # Ensure the dtype matches
|
||||
mapped_material_ids = material_to_slot_array[material_ids]
|
||||
|
||||
# Extend the chunked_material_ids list
|
||||
chunked_material_ids.extend(mapped_material_ids)
|
||||
"""
|
||||
|
||||
chunked_material_ids.extend([material_to_slot[i] for i in material_ids])
|
||||
|
||||
has_processed_chunk = False
|
||||
|
||||
m = shape.transformation.matrix.data
|
||||
mat = np.array(
|
||||
([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1])
|
||||
)
|
||||
verts = self.apply_matrix_to_flat_list(shape.geometry.verts, mat)
|
||||
faces = [f + offset for f in shape.geometry.faces]
|
||||
chunked_verts.extend(verts)
|
||||
chunked_faces.extend(faces)
|
||||
|
||||
offset += len(verts) // 3
|
||||
|
||||
if offset > chunk_size:
|
||||
has_processed_chunk = True
|
||||
self.create_object(chunked_verts, chunked_faces, chunked_materials, chunked_material_ids)
|
||||
chunked_verts = []
|
||||
chunked_faces = []
|
||||
chunked_materials = []
|
||||
chunked_material_ids = []
|
||||
max_slot_index = 0
|
||||
offset = 0
|
||||
pass
|
||||
|
||||
if not iterator.next():
|
||||
if not has_processed_chunk:
|
||||
# The left over chunk
|
||||
self.create_object(chunked_verts, chunked_faces, chunked_materials, chunked_material_ids)
|
||||
break
|
||||
|
||||
bpy.context.scene.collection.children.link(self.collection)
|
||||
print("Finished", time.time() - start)
|
||||
break
|
||||
return {"FINISHED"}
|
||||
|
||||
def apply_matrix_to_flat_list(self, flat_list, matrix):
|
||||
# Convert the flat list to a 2D array with 3 columns (x, y, z)
|
||||
vertices = np.array(flat_list).reshape(-1, 3)
|
||||
# Add a column of ones for homogeneous coordinates (x, y, z, 1)
|
||||
vertices = np.hstack([vertices, np.ones((vertices.shape[0], 1))])
|
||||
# Apply the matrix transformation
|
||||
transformed_vertices = np.dot(vertices, matrix.T)
|
||||
# Discard the homogeneous coordinate and flatten the array
|
||||
return transformed_vertices[:, :3].flatten()
|
||||
|
||||
def create_object(self, verts, faces, materials, material_ids):
|
||||
num_vertices = len(verts) // 3
|
||||
if not num_vertices:
|
||||
return
|
||||
total_faces = len(faces)
|
||||
loop_start = range(0, total_faces, 3)
|
||||
num_loops = total_faces // 3
|
||||
loop_total = [3] * num_loops
|
||||
num_vertex_indices = len(faces)
|
||||
|
||||
mesh = bpy.data.meshes.new("Mesh")
|
||||
|
||||
for material in materials:
|
||||
mesh.materials.append(material)
|
||||
|
||||
mesh.vertices.add(num_vertices)
|
||||
mesh.vertices.foreach_set("co", verts)
|
||||
mesh.loops.add(num_vertex_indices)
|
||||
mesh.loops.foreach_set("vertex_index", faces)
|
||||
mesh.polygons.add(num_loops)
|
||||
mesh.polygons.foreach_set("loop_start", loop_start)
|
||||
mesh.polygons.foreach_set("loop_total", loop_total)
|
||||
mesh.polygons.foreach_set("use_smooth", [0] * total_faces)
|
||||
|
||||
if materials:
|
||||
mesh.polygons.foreach_set("material_index", material_ids)
|
||||
|
||||
mesh.update()
|
||||
|
||||
obj = bpy.data.objects.new("Chunk", mesh)
|
||||
|
||||
self.collection.objects.link(obj)
|
||||
|
||||
Reference in New Issue
Block a user