More refactor of the snapping system, after 7e239ac511e991fd8ccf32add878024d921db38b

This commit is contained in:
Bruno Perdigão
2025-02-12 16:55:25 -03:00
parent 2b7108a1d8
commit 1165ef3f33
2 changed files with 69 additions and 106 deletions
+2 -5
View File
@@ -210,11 +210,6 @@ class Raycast(bonsai.core.tool.Raycast):
points.append(snap_point) points.append(snap_point)
bm.free() bm.free()
# snapping_points = []
# sorted_points = sorted(points, key=lambda x: x[0])
# for p in sorted_points:
# point = copy.deepcopy(p)
# snapping_points.append(point[1])
return points return points
@@ -245,6 +240,8 @@ class Raycast(bonsai.core.tool.Raycast):
snap_point = { snap_point = {
"type": "Vertex", "type": "Vertex",
"point": vertex, "point": vertex,
"distance": distance,
"object": None,
} }
polyline_verts.append(snap_point) polyline_verts.append(snap_point)
+67 -101
View File
@@ -245,10 +245,10 @@ class Snap(bonsai.core.tool.Snap):
# Creates a mixed snap point between the locked axis and the object snap # Creates a mixed snap point between the locked axis and the object snap
# Then it sorts them to get the shortest first # Then it sorts them to get the shortest first
intersections = [] intersections = []
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point[0], Vector((1, 0, 0)))) intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point, Vector((1, 0, 0))))
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point[0], Vector((0, 1, 0)))) intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point, Vector((0, 1, 0))))
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point[0], Vector((0, 0, 1)))) intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point, Vector((0, 0, 1))))
sorted_intersections = sorted(((i, "Mix") for i in intersections if i is not None), reverse=False) sorted_intersections = sorted((i for i in intersections if i is not None), reverse=False)
return sorted_intersections return sorted_intersections
@classmethod @classmethod
@@ -382,12 +382,9 @@ class Snap(bonsai.core.tool.Snap):
if polyline_points: if polyline_points:
snap_points = tool.Raycast.ray_cast_to_polyline(context, event) snap_points = tool.Raycast.ray_cast_to_polyline(context, event)
if snap_points: if snap_points:
detected_snaps.append( for point in snap_points:
{ point["group"] = "Polyline"
"group": "Polyline", detected_snaps.append(point)
"points": snap_points,
}
)
# Measure # Measure
measure_data = context.scene.BIMPolylineProperties.measurement_polyline measure_data = context.scene.BIMPolylineProperties.measurement_polyline
@@ -395,12 +392,9 @@ class Snap(bonsai.core.tool.Snap):
measure_points = measure.polyline_points measure_points = measure.polyline_points
snap_points = tool.Raycast.ray_cast_to_measure(context, event, measure_points) snap_points = tool.Raycast.ray_cast_to_measure(context, event, measure_points)
if snap_points: if snap_points:
detected_snaps.append( for point in snap_points:
{ point["group"] = "Measure"
"group": "Measure", detected_snaps.append(point)
"points": snap_points,
}
)
# Edge-Vertex # Edge-Vertex
for obj in objs_to_raycast: for obj in objs_to_raycast:
@@ -408,29 +402,23 @@ class Snap(bonsai.core.tool.Snap):
if len(obj.data.polygons) == 0: if len(obj.data.polygons) == 0:
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, obj) snap_points = tool.Raycast.ray_cast_by_proximity(context, event, obj)
if snap_points: if snap_points:
detected_snaps.append( for point in snap_points:
{ point["group"] = "Edge-Vertex"
"group": "Edge-Vertex", detected_snaps.append(point)
"object": obj,
"points": snap_points,
}
)
if obj.type == "CURVE": if obj.type == "CURVE":
new_object = bpy.data.objects.new("new_object", obj.to_mesh().copy()) new_object = bpy.data.objects.new("new_object", obj.to_mesh().copy())
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, new_object) snap_points = tool.Raycast.ray_cast_by_proximity(context, event, new_object)
if snap_points: if snap_points:
detected_snaps.append( for point in snap_points:
{ point["group"] = "Edge-Vertex"
"group": "Edge-Vertex", detected_snaps.append(point)
"object": obj,
"points": snap_points,
}
)
if obj.type == "EMPTY": if obj.type == "EMPTY":
snap_point = { snap_point = {
"points": [{"type": "Vertex", "point": obj.location, "distance": 10, "object": obj}], # TODO Get the real distance "type": "Vertex",
"group": "Edge-Vertex", "point": obj.location,
"distance": 10,# TODO Get the real distance
"object": obj, "object": obj,
"group": "Edge-Vertex",
} }
detected_snaps.append(snap_point) detected_snaps.append(snap_point)
@@ -438,28 +426,32 @@ class Snap(bonsai.core.tool.Snap):
if (space.shading.type == "SOLID" and space.shading.show_xray) or ( if (space.shading.type == "SOLID" and space.shading.show_xray) or (
space.shading.type == "WIREFRAME" and space.shading.show_xray_wireframe space.shading.type == "WIREFRAME" and space.shading.show_xray_wireframe
): ):
results = []
for obj in objs_to_raycast: for obj in objs_to_raycast:
snap_obj, hit, face_index = cast_rays_to_single_object(obj, mouse_pos) results.append(cast_rays_to_single_object(obj, mouse_pos))
if hit is not None: else:
results = []
results.append(cast_rays_and_get_best_object(objs_to_raycast, mouse_pos))
for result in results:
snap_obj = result[0]
hit = result[1]
face_index = result[2]
if hit is not None:
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, snap_obj, snap_obj.data.polygons[face_index])
if snap_points:
for point in snap_points:
point["group"] = "Object"
detected_snaps.append(point)
else:
snap_point = { snap_point = {
"point": hit, "point": hit,
"type": "Face",
"group": "Object", "group": "Object",
"object": snap_obj, "object": snap_obj,
"face_index": face_index, "face_index": face_index,
"distance": 10, # TODO Get the real distance "distance": 10, # TODO Get the real distance
} }
detected_snaps.append(snap_point) detected_snaps.append(snap_point)
else:
snap_obj, hit, face_index = cast_rays_and_get_best_object(objs_to_raycast, mouse_pos)
if hit is not None:
snap_point = {
"point": hit,
"group": "Object",
"object": snap_obj,
"face_index": face_index,
"distance": 10, # TODO Get the real distance
}
detected_snaps.append(snap_point)
# Axis and Plane # Axis and Plane
elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
@@ -527,7 +519,7 @@ class Snap(bonsai.core.tool.Snap):
@classmethod @classmethod
def select_snapping_points(cls, context, event, tool_state, detected_snaps): def select_snapping_points(cls, context, event, tool_state, detected_snaps):
def filter_snapping_points_based_on_settings(snapping_points): def filter_snapping_points_by_type(snapping_points):
options = ["Plane", "Axis"] options = ["Plane", "Axis"]
props = context.scene.BIMSnapProperties props = context.scene.BIMSnapProperties
for prop in props.__annotations__.keys(): for prop in props.__annotations__.keys():
@@ -537,7 +529,7 @@ class Snap(bonsai.core.tool.Snap):
filtered_points = [point for point in snapping_points if point["type"] in options] filtered_points = [point for point in snapping_points if point["type"] in options]
return filtered_points return filtered_points
def filter_snapping_groups_based_on_settings(detected_snaps): def filter_snapping_points_by_group(detected_snaps):
options = ["Edge-Vertex", "Axis", "Plane"] options = ["Edge-Vertex", "Axis", "Plane"]
props = context.scene.BIMSnapGroups props = context.scene.BIMSnapGroups
for prop in props.__annotations__.keys(): for prop in props.__annotations__.keys():
@@ -546,76 +538,50 @@ class Snap(bonsai.core.tool.Snap):
filtered_groups = [group for group in detected_snaps if group["group"] in options] filtered_groups = [group for group in detected_snaps if group["group"] in options]
return filtered_groups return filtered_groups
filtered_snaps = filter_snapping_groups_based_on_settings(detected_snaps) snaps_by_group = filter_snapping_points_by_group(detected_snaps)
snapping_points = []
edges = [] # Get edges to create edge-intersection snap edges = [] # Get edges to create edge-intersection snap
for snap_group in filtered_snaps: for snapping_point in snaps_by_group:
if snap_group["group"] == "Polyline": if snapping_point["group"] in {"Polyline", "Measure", "Edge-Vertex", "Object"}:
for p in snap_group["points"]: if snapping_point["type"] == "Edge":
snapping_points.append(p) edges.append(snapping_point)
if snap_group["group"] == "Measure": if snapping_point["group"] == "Axis":
for p in snap_group["points"]: axis_start = snapping_point["axis_start"]
snapping_points.append(p) axis_end = snapping_point["axis_end"]
if p["type"] == "Edge":
edges.append(p)
if snap_group["group"] == "Edge-Vertex":
for p in snap_group["points"]:
snapping_points.append(p)
if p["type"] == "Edge":
edges.append(p)
if snap_group["group"] == "Object":
obj = snap_group["object"]
matrix = obj.matrix_world.copy()
face = obj.data.polygons[snap_group["face_index"]]
verts = []
for i in face.vertices:
verts.append(matrix @ obj.data.vertices[i].co)
snap_points = tool.Raycast.ray_cast_by_proximity(context, event, obj, face)
if not snap_points:
snap_group["type"] = "Face"
snapping_points.append(snap_group)
else:
for p in snap_points:
snapping_points.append(p)
if p["type"] == "Edge":
edges.append(p)
for snap_group in filtered_snaps:
if snap_group["group"] == "Axis":
axis_start = snap_group["axis_start"]
axis_end = snap_group["axis_end"]
snapping_points.append(snap_group)
if snap_group["group"] == "Plane":
snapping_points.append(snap_group)
# Edges intersection snap # Edges intersection snap
if edges: if edges:
snap_point = tool.Raycast.ray_cast_to_edge_intersection(context, event, edges) snap_point = tool.Raycast.ray_cast_to_edge_intersection(context, event, edges)
if snap_point: if snap_point:
snapping_points.insert(0, snap_point) snaps_by_group.insert(0, snap_point)
filtered_snapping_points = filter_snapping_points_based_on_settings(snapping_points) snaps_by_type = filter_snapping_points_by_type(snaps_by_group)
filtered_snapping_points = sorted(filtered_snapping_points, key=lambda x: x["distance"]) snaps_by_type = sorted(snaps_by_type, key=lambda x: x["distance"])
# Make Axis first priority # Make Axis first priority
if tool_state.lock_axis or tool_state.axis_method in {"X", "Y", "Z"}: if tool_state.lock_axis or tool_state.axis_method in {"X", "Y", "Z"}:
cls.update_snapping_ref(filtered_snapping_points[0]["point"], filtered_snapping_points[0]["type"]) cls.update_snapping_ref(snaps_by_type[0]["point"], snaps_by_type[0]["type"])
for point in filtered_snapping_points: for point in snaps_by_type:
if point["point"] == "Axis": if point["type"] == "Axis":
if filtered_snapping_points[0]["type"] not in {"Axis", "Plane"}: if snaps_by_type[0]["type"] not in {"Axis", "Plane"}:
# TODO Fix this based on the dictionary # TODO Fix this based on the dictionary
mixed_snap = cls.mix_snap_and_axis(filtered_snapping_points[0], axis_start, axis_end) obj = snaps_by_type[0]["object"]
mixed_snap = cls.mix_snap_and_axis(snaps_by_type[0]["point"], axis_start, axis_end)
for mixed_point in mixed_snap: for mixed_point in mixed_snap:
filtered_snapping_points.insert(0, mixed_point) snap_point = {
cls.update_snapping_point(mixed_snap[0]["point"], mixed_snap[0]["type"]) "point": mixed_point,
return filtered_snapping_points "type": "Mix",
"object": obj,
}
snaps_by_type.insert(0, snap_point)
cls.update_snapping_point(snap_point["point"], snap_point["type"])
return snaps_by_type
cls.update_snapping_point(point["point"], point["type"]) cls.update_snapping_point(point["point"], point["type"])
return filtered_snapping_points return snaps_by_type
cls.update_snapping_point( cls.update_snapping_point(
filtered_snapping_points[0]["point"], filtered_snapping_points[0]["type"], filtered_snapping_points[0]["object"] snaps_by_type[0]["point"], snaps_by_type[0]["type"], snaps_by_type[0]["object"]
) )
return filtered_snapping_points return snaps_by_type
@classmethod @classmethod
def modify_snapping_point_selection(cls, snapping_points, lock_axis=False): def modify_snapping_point_selection(cls, snapping_points, lock_axis=False):