Polyline tool initial support for custom transformations.

Still early development. Only works for XY plane.
https://imgur.com/a/qW8gMFW
This commit is contained in:
Bruno Perdigão
2025-02-17 16:35:52 -03:00
parent 5a3a032fe6
commit 247bff4075
3 changed files with 41 additions and 13 deletions
@@ -695,6 +695,8 @@ class PolylineDecorator:
self.draw_batch("LINES", mouse_point + projection_point, decorator_color_unselected, edges)
if axis1 and axis2:
axis1 = [tuple(tool.Polyline.use_transform_orientations(Vector(v))) for v in axis1]
axis2 = [tuple(tool.Polyline.use_transform_orientations(Vector(v))) for v in axis2]
self.line_shader.uniform_float("lineWidth", 1.5)
self.draw_batch("LINES", axis1, highlight_color(axis_color1), [(0, 1)])
self.draw_batch("LINES", axis2, highlight_color(axis_color2), [(0, 1)])
+27 -9
View File
@@ -27,7 +27,7 @@ from dataclasses import dataclass
from lark import Lark, Transformer
from math import degrees, radians, sin, cos, tan
from mathutils import Vector, Matrix
from typing import Optional, Union, Literal
from typing import Optional, Union, Literal, List
class Polyline(bonsai.core.tool.Polyline):
@@ -154,13 +154,15 @@ class Polyline(bonsai.core.tool.Polyline):
else:
# Creates a fake "second to last" point away from the first point but in the same x axis
# this allows to calculate the angle relative to x axis when there is only one point
second_to_last_point = Vector((last_point.x + 1000, last_point.y, last_point.z))
second_to_last_point = Vector((last_point.x + 1000000000, last_point.y, last_point.z))
if tool_state.plane_method == "YZ":
second_to_last_point = Vector((last_point.x, last_point.y + 1000, last_point.z))
second_to_last_point = Vector((last_point.x, last_point.y + 1000000000, last_point.z))
second_to_last_point = tool.Polyline.use_transform_orientations(second_to_last_point)
world_second_to_last_point = Vector((last_point.x + 1000, last_point.y, last_point.z))
world_second_to_last_point = Vector((last_point.x + 1000000000, last_point.y, last_point.z))
if tool_state.plane_method == "YZ":
world_second_to_last_point = Vector((last_point.x, last_point.y + 1000, last_point.z))
world_second_to_last_point = Vector((last_point.x, last_point.y + 1000000000, last_point.z))
world_second_to_last_point = tool.Polyline.use_transform_orientations(world_second_to_last_point)
distance = (mouse_vector - last_point).length
if distance < 0:
@@ -278,7 +280,10 @@ class Polyline(bonsai.core.tool.Polyline):
else:
# Creates a fake "second to last" point away from the first point but in the same x axis
# this allows to calculate the angle relative to x axis when there is only one point
second_to_last_point = Vector((last_point.x + 1000, last_point.y, last_point.z))
second_to_last_point = Vector((last_point.x + 1000000000, last_point.y, last_point.z))
if tool_state.plane_method == "YZ":
second_to_last_point = Vector((last_point.x, last_point.y + 1000000000, last_point.z))
second_to_last_point = tool.Polyline.use_transform_orientations(second_to_last_point)
distance = input_ui.get_number_value("D")
@@ -288,8 +293,8 @@ class Polyline(bonsai.core.tool.Polyline):
rot_vector = tool.Cad.angle_3_vectors(second_to_last_point, last_point, snap_vector, angle, degrees=True)
# When the angle in 180 degrees it might create a rotation vector that is equal to
# when the angle is 0 degress, leading the insertion point to the opposite direction
# This prevents the issue by ensuring the the negative x direction
# when the angle is 0 degrees, leading the insertion point to the opposite direction
# This prevents the issue by ensuring the negative x direction
if round(angle, 4) == round(math.pi, 4):
rot_vector.x = -1.0
@@ -439,7 +444,7 @@ class Polyline(bonsai.core.tool.Polyline):
transformer = InputTransform()
result = transformer.transform(parse_tree)
result = round(result, 5)
result = round(result, 4)
return True, str(result)
except:
return False, "0"
@@ -574,3 +579,16 @@ class Polyline(bonsai.core.tool.Polyline):
measurement_data.total_length = polyline_data[0].total_length
measurement_data.area = polyline_data[0].area
@classmethod
def use_transform_orientations(cls, value:Union[Vector, Matrix]) -> Union[Vector, Matrix]:
custom_orientation = bpy.context.scene.transform_orientation_slots[0].custom_orientation
if custom_orientation:
custom_matrix = custom_orientation.matrix
if isinstance(value, Vector):
result = custom_matrix @ value
else:
result = custom_matrix.inverted() @ value
return result
return value
+12 -4
View File
@@ -188,6 +188,7 @@ class Snap(bonsai.core.tool.Snap):
if not axis:
continue
rot_mat = Matrix.Rotation(math.radians(360 - axis), 3, pivot_axis)
rot_mat = tool.Polyline.use_transform_orientations(rot_mat)
rot_intersection = rot_mat @ translated_intersection
proximity = rot_intersection.y
if tool_state.plane_method == "XZ":
@@ -211,6 +212,7 @@ class Snap(bonsai.core.tool.Snap):
if tool_state.plane_method == "YZ":
axis = 90 - (axis * -1)
rot_mat = Matrix.Rotation(math.radians(360 - axis), 3, pivot_axis)
rot_mat = tool.Polyline.use_transform_orientations(rot_mat)
rot_intersection = rot_mat @ translated_intersection
start, end = create_axis_line_data(rot_mat, last_point)
PolylineDecorator.set_angle_axis_line(start, end)
@@ -229,10 +231,13 @@ class Snap(bonsai.core.tool.Snap):
def mix_snap_and_axis(cls, snap_point, axis_start, axis_end):
# Creates a mixed snap point between the locked axis and the object snap
# Then it sorts them to get the shortest first
x_axis = tool.Polyline.use_transform_orientations(Vector((1, 0, 0)))
y_axis = tool.Polyline.use_transform_orientations(Vector((0, 1, 0)))
z_axis = tool.Polyline.use_transform_orientations(Vector((0, 0, 1)))
intersections = []
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, Vector((0, 1, 0))))
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point, Vector((0, 0, 1))))
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point, x_axis))
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point, y_axis))
intersections.append(tool.Cad.intersect_edge_plane(axis_start, axis_end, snap_point, z_axis))
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
@@ -274,6 +279,9 @@ class Snap(bonsai.core.tool.Snap):
)
def select_plane_method():
if not last_polyline_point:
plane_origin = Vector((0, 0, 0))
plane_normal = Vector((0, 0, 1))
if not tool_state.plane_method:
view_rotation = rv3d.view_rotation
view_location = rv3d.view_location
@@ -302,6 +310,7 @@ class Snap(bonsai.core.tool.Snap):
plane_origin = Vector((last_polyline_point.x, last_polyline_point.y, last_polyline_point.z))
plane_normal = Vector((1, 0, 0))
plane_normal = tool.Polyline.use_transform_orientations(plane_normal)
return plane_origin, plane_normal
def cast_rays_to_single_object(obj, mouse_pos):
@@ -448,7 +457,6 @@ class Snap(bonsai.core.tool.Snap):
tool_state.plane_origin = plane_origin # This will be used along with plane method
intersection = tool.Raycast.ray_cast_to_plane(context, event, plane_origin, plane_normal)
print(intersection)
axis_start = None
axis_end = None