mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +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)
|
||||
|
||||
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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user