Fix #2818. Alignment functions now considers layer set usage offsets.

This commit is contained in:
Dion Moult
2023-03-03 11:55:36 +11:00
parent 4c58ca28e5
commit 5677768e99
@@ -346,28 +346,6 @@ def recalculate_dumb_wall_origin(wall, new_origin=None):
child.matrix_parent_inverse = wall.matrix_world.inverted() child.matrix_parent_inverse = wall.matrix_world.inverted()
class DumbWallFlipper:
def __init__(self, wall):
self.wall = wall
def flip(self):
if (
self.wall.matrix_world.translation - self.wall.matrix_world @ Vector(self.wall.bound_box[0])
).length < 0.001:
recalculate_dumb_wall_origin(self.wall, self.wall.matrix_world @ Vector(self.wall.bound_box[7]))
self.rotate_wall_180()
bpy.context.view_layer.update()
for child in self.wall.children:
child.matrix_parent_inverse = self.wall.matrix_world.inverted()
else:
recalculate_dumb_wall_origin(self.wall)
def rotate_wall_180(self):
flip_matrix = Matrix.Rotation(pi, 4, "Z")
self.wall.data.transform(flip_matrix)
self.wall.rotation_euler.rotate(flip_matrix)
class DumbWallAligner: class DumbWallAligner:
# An alignment shifts the origin of all walls to the closest point on the # An alignment shifts the origin of all walls to the closest point on the
# local X axis of the reference wall. In addition, the Z rotation is copied. # local X axis of the reference wall. In addition, the Z rotation is copied.
@@ -377,61 +355,58 @@ class DumbWallAligner:
self.reference_wall = reference_wall self.reference_wall = reference_wall
def align_centerline(self): def align_centerline(self):
recalculate_dumb_wall_origin(self.wall)
recalculate_dumb_wall_origin(self.reference_wall)
self.align_rotation() self.align_rotation()
width = (Vector(self.wall.bound_box[3]) - Vector(self.wall.bound_box[0])).y l_start = Vector(self.reference_wall.bound_box[0]).lerp(Vector(self.reference_wall.bound_box[3]), 0.5)
reference_width = (Vector(self.reference_wall.bound_box[3]) - Vector(self.reference_wall.bound_box[0])).y l_end = Vector(self.reference_wall.bound_box[4]).lerp(Vector(self.reference_wall.bound_box[7]), 0.5)
if self.is_rotation_flipped(): start = self.reference_wall.matrix_world @ l_start
offset = self.wall.matrix_world.to_quaternion() @ Vector((0, -(reference_width / 2) - (width / 2), 0)) end = self.reference_wall.matrix_world @ l_end
else:
offset = self.wall.matrix_world.to_quaternion() @ Vector((0, (reference_width / 2) - (width / 2), 0))
self.align( l_snap_point = Vector(self.wall.bound_box[0]).lerp(Vector(self.wall.bound_box[3]), 0.5)
self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[0]), snap_point = self.wall.matrix_world @ l_snap_point
self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[4]), offset = snap_point - self.wall.matrix_world.translation
offset,
) point, _ = mathutils.geometry.intersect_point_line(snap_point, start, end)
new_origin = point - offset
self.wall.matrix_world.translation[0], self.wall.matrix_world.translation[1] = new_origin.xy
def align_last_layer(self): def align_last_layer(self):
recalculate_dumb_wall_origin(self.wall)
recalculate_dumb_wall_origin(self.reference_wall)
self.align_rotation() self.align_rotation()
if self.is_rotation_flipped(): if self.is_rotation_flipped():
DumbWallFlipper(self.wall).flip() DumbWallJoiner().flip(self.wall)
bpy.context.view_layer.update() bpy.context.view_layer.update()
start = self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[3]) start = self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[3])
end = self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[7]) end = self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[7])
wall_width = (Vector(self.wall.bound_box[3]) - Vector(self.wall.bound_box[0])).y snap_point = self.wall.matrix_world @ Vector(self.wall.bound_box[3])
offset = snap_point - self.wall.matrix_world.translation
offset = self.wall.matrix_world.to_quaternion() @ Vector((0, -wall_width, 0)) point, _ = mathutils.geometry.intersect_point_line(snap_point, start, end)
self.align(start, end, offset)
new_origin = point - offset
self.wall.matrix_world.translation[0], self.wall.matrix_world.translation[1] = new_origin.xy
def align_first_layer(self): def align_first_layer(self):
recalculate_dumb_wall_origin(self.wall)
recalculate_dumb_wall_origin(self.reference_wall)
self.align_rotation() self.align_rotation()
if self.is_rotation_flipped(): if self.is_rotation_flipped():
DumbWallFlipper(self.wall).flip() DumbWallJoiner().flip(self.wall)
bpy.context.view_layer.update() bpy.context.view_layer.update()
start = self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[0]) start = self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[0])
end = self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[4]) end = self.reference_wall.matrix_world @ Vector(self.reference_wall.bound_box[4])
self.align(start, end) snap_point = self.wall.matrix_world @ Vector(self.wall.bound_box[0])
offset = snap_point - self.wall.matrix_world.translation
def align(self, start, end, offset=None): point, _ = mathutils.geometry.intersect_point_line(snap_point, start, end)
if offset is None:
offset = Vector((0, 0, 0)) new_origin = point - offset
point, distance = mathutils.geometry.intersect_point_line(self.wall.matrix_world.translation, start, end) self.wall.matrix_world.translation[0], self.wall.matrix_world.translation[1] = new_origin.xy
new_origin = point + offset
self.wall.matrix_world.translation[0] = new_origin[0]
self.wall.matrix_world.translation[1] = new_origin[1]
def align_rotation(self): def align_rotation(self):
reference = (self.reference_wall.matrix_world.to_quaternion() @ Vector((1, 0, 0))).to_2d() reference = (self.reference_wall.matrix_world.to_quaternion() @ Vector((1, 0, 0))).to_2d()