mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 06:39:13 +00:00
Add dimensions dialog for reference image and update scaling logic
This commit is contained in:
@@ -3689,16 +3689,90 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
|||||||
options={"SKIP_SAVE"},
|
options={"SKIP_SAVE"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
x_length: bpy.props.FloatProperty(
|
||||||
|
name="X Length",
|
||||||
|
description="Width of the reference image in project units",
|
||||||
|
default=1.0,
|
||||||
|
min=0.001,
|
||||||
|
soft_min=0.01,
|
||||||
|
precision=3,
|
||||||
|
)
|
||||||
|
y_length: bpy.props.FloatProperty(
|
||||||
|
name="Y Length",
|
||||||
|
description="Height of the reference image in project units",
|
||||||
|
default=1.0,
|
||||||
|
min=0.001,
|
||||||
|
soft_min=0.01,
|
||||||
|
precision=3,
|
||||||
|
)
|
||||||
|
|
||||||
|
_show_dimensions_dialog: bpy.props.BoolProperty(default=False, options={"HIDDEN", "SKIP_SAVE"})
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
if Path(tool.Ifc.get_path()).is_file():
|
|
||||||
layout.prop(self, "use_relative_path")
|
if getattr(self, '_show_dimensions_dialog', False):
|
||||||
|
if tool.Ifc.get():
|
||||||
|
length_unit = ifcopenshell.util.unit.get_project_unit(tool.Ifc.get(), "LENGTHUNIT")
|
||||||
|
if length_unit:
|
||||||
|
unit_name = ifcopenshell.util.unit.get_full_unit_name(length_unit).lower()
|
||||||
|
else:
|
||||||
|
unit_name = "project units"
|
||||||
|
layout.label(text=f"Set Reference Image Dimensions (in {unit_name}):")
|
||||||
|
else:
|
||||||
|
layout.label(text="Set Reference Image Dimensions (in project units):")
|
||||||
|
layout.separator()
|
||||||
|
layout.prop(self, "x_length")
|
||||||
|
layout.prop(self, "y_length")
|
||||||
else:
|
else:
|
||||||
self.use_relative_path = False
|
if Path(tool.Ifc.get_path()).is_file():
|
||||||
layout.label(text="Save the .ifc file first ")
|
layout.prop(self, "use_relative_path")
|
||||||
layout.label(text="to use relative paths.")
|
else:
|
||||||
layout.prop(self, "override_existing_image")
|
self.use_relative_path = False
|
||||||
layout.prop(self, "use_existing_object_by_name")
|
layout.label(text="Save the .ifc file first ")
|
||||||
|
layout.label(text="to use relative paths.")
|
||||||
|
layout.prop(self, "override_existing_image")
|
||||||
|
layout.prop(self, "use_existing_object_by_name")
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
if not getattr(self, '_show_dimensions_dialog', False):
|
||||||
|
context.window_manager.fileselect_add(self)
|
||||||
|
return {'RUNNING_MODAL'}
|
||||||
|
else:
|
||||||
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
if not getattr(self, '_show_dimensions_dialog', False):
|
||||||
|
abs_path = Path(self.filepath).absolute().resolve()
|
||||||
|
if self.override_existing_image:
|
||||||
|
params = {"check_existing": True, "force_reload": True}
|
||||||
|
else:
|
||||||
|
params = {"check_existing": False}
|
||||||
|
|
||||||
|
try:
|
||||||
|
image = load_image(abs_path.name, str(abs_path.parent), **params)
|
||||||
|
|
||||||
|
image_width_px = image.size[0]
|
||||||
|
image_height_px = image.size[1]
|
||||||
|
aspect_ratio = image_width_px / image_height_px
|
||||||
|
|
||||||
|
if aspect_ratio >= 1.0:
|
||||||
|
self.x_length = 1.0
|
||||||
|
self.y_length = 1.0 / aspect_ratio
|
||||||
|
else:
|
||||||
|
self.x_length = aspect_ratio
|
||||||
|
self.y_length = 1.0
|
||||||
|
|
||||||
|
bpy.data.images.remove(image)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.report({'ERROR'}, f"Failed to load image: {str(e)}")
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
self._show_dimensions_dialog = True
|
||||||
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
|
return self._execute(context)
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
space = tool.Blender.get_view3d_space()
|
space = tool.Blender.get_view3d_space()
|
||||||
@@ -3717,11 +3791,13 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
|||||||
params = {"check_existing": True, "force_reload": True}
|
params = {"check_existing": True, "force_reload": True}
|
||||||
else:
|
else:
|
||||||
params = {"check_existing": False}
|
params = {"check_existing": False}
|
||||||
image = load_image(abs_path.name, abs_path.parent, **params)
|
image = load_image(abs_path.name, str(abs_path.parent), **params)
|
||||||
|
|
||||||
def bm_add_image_plane(mesh):
|
def bm_add_image_plane(mesh):
|
||||||
bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True)
|
bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True)
|
||||||
plane_scale = (Vector(image.size) / min(image.size)).to_3d()
|
|
||||||
|
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
|
||||||
|
plane_scale = Vector((self.x_length * unit_scale / 2.0, self.y_length * unit_scale / 2.0, 1.0))
|
||||||
matrix = Matrix.LocRotScale(None, None, plane_scale)
|
matrix = Matrix.LocRotScale(None, None, plane_scale)
|
||||||
bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, matrix=matrix, calc_uvs=False)
|
bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, matrix=matrix, calc_uvs=False)
|
||||||
|
|
||||||
@@ -3730,12 +3806,22 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
|||||||
else:
|
else:
|
||||||
uv_layer = bm.loops.layers.uv.active
|
uv_layer = bm.loops.layers.uv.active
|
||||||
|
|
||||||
aspect_ratio = image.size[1] / image.size[0]
|
min_x = min(v.co.x for v in bm.verts)
|
||||||
|
max_x = max(v.co.x for v in bm.verts)
|
||||||
|
min_y = min(v.co.y for v in bm.verts)
|
||||||
|
max_y = max(v.co.y for v in bm.verts)
|
||||||
|
|
||||||
|
width = max_x - min_x
|
||||||
|
height = max_y - min_y
|
||||||
|
|
||||||
for face in bm.faces:
|
for face in bm.faces:
|
||||||
for loop in face.loops:
|
for loop in face.loops:
|
||||||
vert = loop.vert
|
vert = loop.vert
|
||||||
v = (vert.co.y * 0.5) + 0.5
|
u = (vert.co.x - min_x) / width if width > 0 else 0.5
|
||||||
u = (vert.co.x * 0.5 * aspect_ratio) + 0.5
|
v = (vert.co.y - min_y) / height if height > 0 else 0.5
|
||||||
|
|
||||||
|
u = max(0.0, min(1.0, u))
|
||||||
|
v = max(0.0, min(1.0, v))
|
||||||
loop[uv_layer].uv = (u, v)
|
loop[uv_layer].uv = (u, v)
|
||||||
|
|
||||||
tool.Blender.apply_bmesh(mesh, bm)
|
tool.Blender.apply_bmesh(mesh, bm)
|
||||||
@@ -3768,6 +3854,14 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
|||||||
obj.data["ios_item_ids"] = [item_id] * num_faces
|
obj.data["ios_item_ids"] = [item_id] * num_faces
|
||||||
tool.Blender.Attribute.fill_attribute(obj.data, "ios_item_ids", "FACE", "INT", [item_id] * num_faces)
|
tool.Blender.Attribute.fill_attribute(obj.data, "ios_item_ids", "FACE", "INT", [item_id] * num_faces)
|
||||||
|
|
||||||
|
for item in representation.Items:
|
||||||
|
if item.is_a('IfcPolygonalFaceSet') and item.Coordinates:
|
||||||
|
new_coords = []
|
||||||
|
for vertex in obj.data.vertices:
|
||||||
|
co = obj.matrix_world @ vertex.co
|
||||||
|
new_coords.append([co.x, co.y, co.z])
|
||||||
|
item.Coordinates.CoordList = new_coords
|
||||||
|
|
||||||
tool.Blender.set_active_object(obj)
|
tool.Blender.set_active_object(obj)
|
||||||
|
|
||||||
material = bpy.data.materials.new(name=image_filepath.stem)
|
material = bpy.data.materials.new(name=image_filepath.stem)
|
||||||
@@ -3808,6 +3902,8 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
|||||||
tool.Style.reload_material_from_ifc(material)
|
tool.Style.reload_material_from_ifc(material)
|
||||||
tool.Geometry.record_object_materials(obj)
|
tool.Geometry.record_object_materials(obj)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ConvertSVGToDXF(bpy.types.Operator):
|
class ConvertSVGToDXF(bpy.types.Operator):
|
||||||
bl_idname = "bim.convert_svg_to_dxf"
|
bl_idname = "bim.convert_svg_to_dxf"
|
||||||
|
|||||||
Reference in New Issue
Block a user