diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 5a530990dd..6a8bfe0229 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -265,8 +265,13 @@ class CreateDrawing(bpy.types.Operator): underlay_svg = self.generate_underlay(context) with profile("Generate linework"): + self.projection_mode = "FREESTYLE" + self.projection_mode = "OPENCASCADE" 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"): if tool.Drawing.is_camera_orthographic(): @@ -543,6 +548,44 @@ class CreateDrawing(bpy.types.Operator): 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]: if not ifcopenshell.util.element.get_pset(self.drawing, "EPset_Drawing", "HasLinework"): return @@ -629,8 +672,13 @@ class CreateDrawing(bpy.types.Operator): return svg_path - self.move_projection_to_bottom(root) - self.merge_linework_and_add_metadata(root) + if self.camera.data.BIMCameraProperties.cut_mode == "BISECT": + 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": # shapely variant @@ -1007,6 +1055,11 @@ class CreateDrawing(bpy.types.Operator): except: 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): join_criteria = ifcopenshell.util.element.get_pset(self.camera_element, "EPset_Drawing", "JoinCriteria") if join_criteria: diff --git a/src/bonsai/bonsai/bim/module/drawing/prop.py b/src/bonsai/bonsai/bim/module/drawing/prop.py index 9a631377d4..9258de76ff 100644 --- a/src/bonsai/bonsai/bim/module/drawing/prop.py +++ b/src/bonsai/bonsai/bim/module/drawing/prop.py @@ -395,6 +395,11 @@ class BIMCameraProperties(PropertyGroup): default="NONE", 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_linework: BoolProperty(name="Linework", default=True, update=update_has_linework) has_annotation: BoolProperty(name="Annotation", default=True, update=update_has_annotation) diff --git a/src/bonsai/bonsai/bim/module/drawing/ui.py b/src/bonsai/bonsai/bim/module/drawing/ui.py index 2c2242e950..33f24a235b 100644 --- a/src/bonsai/bonsai/bim/module/drawing/ui.py +++ b/src/bonsai/bonsai/bim/module/drawing/ui.py @@ -66,6 +66,7 @@ class BIM_PT_camera(Panel): row = self.layout.row() row.prop(props, "fill_mode") row = self.layout.row() + row.prop(props, "cut_mode") row = self.layout.row() row.prop(props, "width")