mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 03:05:33 +00:00
New bisect-based drawing cut mode. This replaces OCC's cut (but keeps the projection HLR) with a blender bisect based cut
This commit is contained in:
@@ -265,8 +265,13 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
underlay_svg = self.generate_underlay(context)
|
underlay_svg = self.generate_underlay(context)
|
||||||
|
|
||||||
with profile("Generate linework"):
|
with profile("Generate linework"):
|
||||||
|
self.projection_mode = "FREESTYLE"
|
||||||
|
self.projection_mode = "OPENCASCADE"
|
||||||
if tool.Drawing.is_camera_orthographic():
|
if tool.Drawing.is_camera_orthographic():
|
||||||
linework_svg = self.generate_linework(context)
|
if self.projection_mode == "OPENCASCADE":
|
||||||
|
linework_svg = self.generate_linework(context)
|
||||||
|
elif self.projection_mode == "FREESTYLE":
|
||||||
|
pass
|
||||||
|
|
||||||
with profile("Generate annotation"):
|
with profile("Generate annotation"):
|
||||||
if tool.Drawing.is_camera_orthographic():
|
if tool.Drawing.is_camera_orthographic():
|
||||||
@@ -543,6 +548,44 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
self.file.createIfcDirection(forward.tolist()),
|
self.file.createIfcDirection(forward.tolist()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def generate_bisect_linework(self, context: bpy.types.Context, root):
|
||||||
|
camera_matrix_i = context.scene.camera.matrix_world.inverted()
|
||||||
|
|
||||||
|
group = root.find("{http://www.w3.org/2000/svg}g")
|
||||||
|
raw_width, raw_height = self.get_camera_dimensions()
|
||||||
|
x_offset = raw_width / 2
|
||||||
|
y_offset = raw_height / 2
|
||||||
|
svg_scale = self.scale * 1000 # IFC is in meters, SVG is in mm
|
||||||
|
|
||||||
|
for obj in context.visible_objects:
|
||||||
|
if obj.type != "MESH":
|
||||||
|
continue
|
||||||
|
if not (element := tool.Ifc.get_entity(obj)):
|
||||||
|
continue
|
||||||
|
if not tool.Drawing.is_intersecting_camera(obj, context.scene.camera):
|
||||||
|
continue
|
||||||
|
verts, edges = tool.Drawing.bisect_mesh(obj, context.scene.camera)
|
||||||
|
|
||||||
|
g = etree.SubElement(root, "{http://www.w3.org/2000/svg}g")
|
||||||
|
g.attrib["{http://www.ifcopenshell.org/ns}guid"] = element.GlobalId
|
||||||
|
g.attrib["{http://www.ifcopenshell.org/ns}name"] = element.Name or ""
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
for edge in edges:
|
||||||
|
start = [round(o, 5) for o in (camera_matrix_i @ Vector(verts[edge[0]])).xy]
|
||||||
|
end = [round(o, 5) for o in (camera_matrix_i @ Vector(verts[edge[1]])).xy]
|
||||||
|
coords = [start, end]
|
||||||
|
d = " ".join(
|
||||||
|
[
|
||||||
|
"L{},{}".format((x_offset + p[0]) * svg_scale, (y_offset - p[1]) * svg_scale)
|
||||||
|
for p in coords
|
||||||
|
]
|
||||||
|
)
|
||||||
|
d = "M{}".format(d[1:])
|
||||||
|
path = etree.SubElement(g, "{http://www.w3.org/2000/svg}path")
|
||||||
|
path.attrib["d"] = d
|
||||||
|
group.append(g)
|
||||||
|
|
||||||
def generate_linework(self, context: bpy.types.Context) -> Union[str, None]:
|
def generate_linework(self, context: bpy.types.Context) -> Union[str, None]:
|
||||||
if not ifcopenshell.util.element.get_pset(self.drawing, "EPset_Drawing", "HasLinework"):
|
if not ifcopenshell.util.element.get_pset(self.drawing, "EPset_Drawing", "HasLinework"):
|
||||||
return
|
return
|
||||||
@@ -629,8 +672,13 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
|
|
||||||
return svg_path
|
return svg_path
|
||||||
|
|
||||||
self.move_projection_to_bottom(root)
|
if self.camera.data.BIMCameraProperties.cut_mode == "BISECT":
|
||||||
self.merge_linework_and_add_metadata(root)
|
self.remove_cut_linework(root)
|
||||||
|
self.generate_bisect_linework(context, root)
|
||||||
|
self.merge_linework_and_add_metadata(root)
|
||||||
|
elif self.camera.data.BIMCameraProperties.cut_mode == "OPENCASCADE":
|
||||||
|
self.move_projection_to_bottom(root)
|
||||||
|
self.merge_linework_and_add_metadata(root)
|
||||||
|
|
||||||
if self.camera.data.BIMCameraProperties.fill_mode == "SHAPELY":
|
if self.camera.data.BIMCameraProperties.fill_mode == "SHAPELY":
|
||||||
# shapely variant
|
# shapely variant
|
||||||
@@ -1007,6 +1055,11 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
def remove_cut_linework(self, root):
|
||||||
|
for el in root.findall(".//{http://www.w3.org/2000/svg}g[@{http://www.ifcopenshell.org/ns}guid]"):
|
||||||
|
if "projection" not in el.get("class", "").split():
|
||||||
|
el.getparent().remove(el)
|
||||||
|
|
||||||
def merge_linework_and_add_metadata(self, root):
|
def merge_linework_and_add_metadata(self, root):
|
||||||
join_criteria = ifcopenshell.util.element.get_pset(self.camera_element, "EPset_Drawing", "JoinCriteria")
|
join_criteria = ifcopenshell.util.element.get_pset(self.camera_element, "EPset_Drawing", "JoinCriteria")
|
||||||
if join_criteria:
|
if join_criteria:
|
||||||
|
|||||||
@@ -395,6 +395,11 @@ class BIMCameraProperties(PropertyGroup):
|
|||||||
default="NONE",
|
default="NONE",
|
||||||
name="Fill Mode",
|
name="Fill Mode",
|
||||||
)
|
)
|
||||||
|
cut_mode: EnumProperty(
|
||||||
|
items=[("BISECT", "Bisect", ""), ("OPENCASCADE", "OpenCASCADE", "")],
|
||||||
|
default="BISECT",
|
||||||
|
name="Cut Mode",
|
||||||
|
)
|
||||||
has_underlay: BoolProperty(name="Underlay", default=False, update=update_has_underlay)
|
has_underlay: BoolProperty(name="Underlay", default=False, update=update_has_underlay)
|
||||||
has_linework: BoolProperty(name="Linework", default=True, update=update_has_linework)
|
has_linework: BoolProperty(name="Linework", default=True, update=update_has_linework)
|
||||||
has_annotation: BoolProperty(name="Annotation", default=True, update=update_has_annotation)
|
has_annotation: BoolProperty(name="Annotation", default=True, update=update_has_annotation)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class BIM_PT_camera(Panel):
|
|||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.prop(props, "fill_mode")
|
row.prop(props, "fill_mode")
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
|
row.prop(props, "cut_mode")
|
||||||
|
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.prop(props, "width")
|
row.prop(props, "width")
|
||||||
|
|||||||
Reference in New Issue
Block a user