Skip to content
This repository was archived by the owner on Nov 24, 2024. It is now read-only.

Commit b61a11d

Browse files
committed
reworked detecting neighbour walls when placing new ones
hopefully it will be a bit more natural now - please give feeback before - https://imgur.com/a/VYQt5ua now - https://imgur.com/a/5LRAmrd
1 parent 012da8f commit b61a11d

1 file changed

Lines changed: 29 additions & 11 deletions

File tree

  • src/blenderbim/blenderbim/bim/module/model

src/blenderbim/blenderbim/bim/module/model/wall.py

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -534,31 +534,49 @@ def is_near(self, point1, point2):
534534
return (point1 - point2).length < 0.1
535535

536536
def derive_from_cursor(self):
537+
RAYCAST_PRECISION = 0.01
537538
self.location = bpy.context.scene.cursor.location
538539
if self.collection:
539540
for sibling_obj in self.collection.objects:
540541
if not isinstance(sibling_obj.data, bpy.types.Mesh):
541542
continue
542543
if "IfcWall" not in sibling_obj.name:
543544
continue
544-
local_location = sibling_obj.matrix_world.inverted() @ self.location
545+
inv_obj_matrix = sibling_obj.matrix_world.inverted()
546+
local_location = inv_obj_matrix @ self.location
545547
try:
546-
raycast = sibling_obj.closest_point_on_mesh(local_location, distance=0.01)
548+
raycast = sibling_obj.closest_point_on_mesh(local_location, distance=RAYCAST_PRECISION)
547549
except:
548550
# If the mesh has no faces
549551
raycast = [None]
550552
if not raycast[0]:
551553
continue
552554
for face in sibling_obj.data.polygons:
553-
if (
554-
abs(face.normal.y) >= 0.75
555-
and abs(mathutils.geometry.distance_point_to_plane(local_location, face.center, face.normal))
556-
< 0.01
557-
):
558-
# Rotate the wall in the direction of the face normal
559-
normal = (sibling_obj.matrix_world.to_quaternion() @ face.normal).normalized()
560-
self.rotation = math.atan2(normal[1], normal[0])
561-
break
555+
normal = (sibling_obj.matrix_world.to_quaternion() @ face.normal).normalized()
556+
face_center = sibling_obj.matrix_world @ face.center
557+
if normal.z != 0 or abs(mathutils.geometry.distance_point_to_plane(self.location, face_center, normal)) > 0.01:
558+
continue
559+
560+
rotation = math.atan2(normal[1], normal[0])
561+
rotated_y_axis = Matrix.Rotation(-rotation, 4, "Z")[1].xyz
562+
563+
# since wall thickness goes by local Y+ axis
564+
# we find best position for the next wall
565+
# by finding the face of another wall that will be very close to the some test point.
566+
# test point is calculated by applying to cursor position some little offset along the face
567+
#
568+
# a bit different offset to be safe on raycast
569+
test_pos = self.location + rotated_y_axis * RAYCAST_PRECISION * 1.1
570+
test_pos_local = inv_obj_matrix @ test_pos
571+
raycast = sibling_obj.closest_point_on_mesh(test_pos_local, distance=RAYCAST_PRECISION)
572+
573+
if not raycast[0]:
574+
continue
575+
self.rotation = rotation
576+
break
577+
578+
if self.rotation != 0:
579+
break
562580
return self.create_wall()
563581

564582
def create_wall(self):

0 commit comments

Comments
 (0)