Polyline tool: improved plane selection method and decorators

This commit is contained in:
Bruno Perdigão
2024-08-16 17:04:39 -03:00
committed by Bruno Perdigão
parent 04088af2b6
commit 1dc6d4935e
2 changed files with 67 additions and 19 deletions
@@ -23,6 +23,7 @@ import bmesh
import bonsai.tool as tool import bonsai.tool as tool
from math import sin, cos, radians, degrees, atan2, acos from math import sin, cos, radians, degrees, atan2, acos
from bpy.types import SpaceView3D from bpy.types import SpaceView3D
import math
from mathutils import Vector, Matrix from mathutils import Vector, Matrix
from gpu_extras.batch import batch_for_shader from gpu_extras.batch import batch_for_shader
from typing import Union from typing import Union
@@ -337,10 +338,19 @@ class WallPolylineDecorator:
cls.axis_start = start cls.axis_start = start
cls.axis_end = end cls.axis_end = end
@classmethod
def set_axis_rectangle(cls, corners):
cls.axis_rectangle = corners
@classmethod @classmethod
def set_use_default_container(cls, value=False): def set_use_default_container(cls, value=False):
cls.use_default_container = value cls.use_default_container = value
@classmethod
def set_plane(cls, plane_origin, plane_normal):
cls.plane_origin = plane_origin
cls.plane_normal = plane_normal
@classmethod @classmethod
def calculate_distance_and_angle(cls, context, is_input_on): def calculate_distance_and_angle(cls, context, is_input_on):
@@ -534,3 +544,9 @@ class WallPolylineDecorator:
if snap_prop.snap_type == "Axis": if snap_prop.snap_type == "Axis":
self.line_shader.uniform_float("lineWidth", 0.75) self.line_shader.uniform_float("lineWidth", 0.75)
self.draw_batch("LINES", [self.axis_start, self.axis_end], decorator_color_unselected, [(0, 1)]) self.draw_batch("LINES", [self.axis_start, self.axis_end], decorator_color_unselected, [(0, 1)])
if self.plane_normal:
self.draw_batch(
"TRIS", [*self.axis_rectangle], (1, 1, 1, 0.1), [(0, 1, 3), (0, 2, 3)]
)
+51 -19
View File
@@ -166,14 +166,39 @@ class Snap(bonsai.core.tool.Snap):
@classmethod @classmethod
def snap_on_axis(cls, intersection, lock_axis=None): def snap_on_axis(cls, intersection, lock_axis=None):
def create_axis_line(rot_mat, origin): def create_axis_line_data(rot_mat, origin):
length = 1000 length = 1000
direction = Vector((1, 0, 0)) direction = Vector((1, 0, 0))
if cls.snap_plane_method == "YZ":
direction = Vector((0, 0, 1))
rot_dir = rot_mat.inverted() @ direction rot_dir = rot_mat.inverted() @ direction
start = origin + rot_dir * length start = origin + rot_dir * length
end = origin - rot_dir * length end = origin - rot_dir * length
return start, end return start, end
def create_axis_rectangle_data(origin):
size = 0.5
direction = Vector((1, 0, 0))
if cls.snap_plane_method == "YZ":
direction = Vector((0, 0, 1))
rot_mat = Matrix.Rotation(math.radians(360), 3, pivot_axis)
rot_dir = rot_mat.inverted() @ direction
v1 = origin + rot_dir * 0
v2 = origin + rot_dir * size
if cls.snap_plane_method == "XY":
angle = 270
else:
angle = 90
rot_mat = Matrix.Rotation(math.radians(angle), 3, pivot_axis)
rot_dir = rot_mat.inverted() @ direction
v3 = origin + rot_dir * size
v4 = v2 + rot_dir * size
return (v1, v2, v3, v4)
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
polyline_data = bpy.context.scene.BIMModelProperties.polyline_point polyline_data = bpy.context.scene.BIMModelProperties.polyline_point
if polyline_data: if polyline_data:
@@ -192,19 +217,32 @@ class Snap(bonsai.core.tool.Snap):
else: else:
snap_axis = [lock_axis] snap_axis = [lock_axis]
pivot_axis = "Z"
if cls.snap_plane_method == "XZ":
pivot_axis = "Y"
if cls.snap_plane_method == "YZ":
pivot_axis = "X"
rectangle_data = create_axis_rectangle_data(last_point)
WallPolylineDecorator.set_axis_rectangle(rectangle_data)
for axis in snap_axis: for axis in snap_axis:
rot_mat = Matrix.Rotation(math.radians(360 - axis), 3, "Z") rot_mat = Matrix.Rotation(math.radians(360 - axis), 3, pivot_axis)
start, end = create_axis_line(rot_mat, last_point) start, end = create_axis_line_data(rot_mat, last_point)
rot_intersection = rot_mat @ translated_intersection rot_intersection = rot_mat @ translated_intersection
proximity = rot_intersection.y
if cls.snap_plane_method == "XZ":
proximity = rot_intersection.z
WallPolylineDecorator.set_angle_axis_line(start, end) WallPolylineDecorator.set_angle_axis_line(start, end)
if lock_axis: if lock_axis:
is_on_rot_axis = True is_on_rot_axis = True
else: else:
is_on_rot_axis = abs(rot_intersection.y) <= 0.15 is_on_rot_axis = abs(proximity) <= 0.15
if is_on_rot_axis: if is_on_rot_axis:
# Snap to axis # Snap to axis
rot_intersection = Vector((rot_intersection.x, 0, rot_intersection.z)) rot_intersection = Vector((rot_intersection.x, 0, rot_intersection.z))
if cls.snap_plane_method == "XZ":
rot_intersection = Vector((rot_intersection.x, rot_intersection.y, 0))
# Convert it back # Convert it back
snap_intersection = rot_mat.inverted() @ rot_intersection + last_point snap_intersection = rot_mat.inverted() @ rot_intersection + last_point
return snap_intersection, axis, start, end return snap_intersection, axis, start, end
@@ -272,28 +310,21 @@ class Snap(bonsai.core.tool.Snap):
if cls.snap_plane_method == "XY": if cls.snap_plane_method == "XY":
if cls.use_default_container: if cls.use_default_container:
plane_origin_point = elevation plane_origin = Vector((0, 0, elevation))
elif not last_polyline_point: elif not last_polyline_point:
plane_origin_point = 0 plane_origin = Vector((0, 0, 0))
else: else:
plane_origin_point = last_polyline_point.z plane_origin = Vector((last_polyline_point.x, last_polyline_point.y, last_polyline_point.z))
plane_origin = Vector((0, 0, plane_origin_point))
plane_normal = Vector((0, 0, 1)) plane_normal = Vector((0, 0, 1))
elif cls.snap_plane_method == "XZ": elif cls.snap_plane_method == "XZ":
if not last_polyline_point: if last_polyline_point:
plane_origin_point = 0 plane_origin = Vector((last_polyline_point.x, last_polyline_point.y, last_polyline_point.z))
else:
plane_origin_point = last_polyline_point.y
plane_origin = Vector((0, plane_origin_point, 0))
plane_normal = Vector((0, 1, 0)) plane_normal = Vector((0, 1, 0))
elif cls.snap_plane_method == "YZ": elif cls.snap_plane_method == "YZ":
if not last_polyline_point: if last_polyline_point:
plane_origin_point = 0 plane_origin = Vector((last_polyline_point.x, last_polyline_point.y, last_polyline_point.z))
else:
plane_origin_point = last_polyline_point.x
plane_origin = Vector((plane_origin_point, 0, 0))
plane_normal = Vector((1, 0, 0)) plane_normal = Vector((1, 0, 0))
return plane_origin, plane_normal return plane_origin, plane_normal
@@ -350,9 +381,10 @@ class Snap(bonsai.core.tool.Snap):
elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
plane_origin, plane_normal = select_plane_method() plane_origin, plane_normal = select_plane_method()
WallPolylineDecorator.set_plane(plane_origin, plane_normal)
intersection = tool.Raycast.ray_cast_to_plane(context, event, plane_origin, plane_normal) intersection = tool.Raycast.ray_cast_to_plane(context, event, plane_origin, plane_normal)
if cls.use_default_container: if cls.snap_plane_method in {"XY", "XZ", "YZ"} :
# Locks snap into an angle axis # Locks snap into an angle axis
if event.shift: if event.shift:
rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, cls.snap_angle) rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, cls.snap_angle)