mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-16 13:46:54 +00:00
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
This commit is contained in:
@@ -534,6 +534,7 @@ class DumbWallGenerator:
|
|||||||
return (point1 - point2).length < 0.1
|
return (point1 - point2).length < 0.1
|
||||||
|
|
||||||
def derive_from_cursor(self):
|
def derive_from_cursor(self):
|
||||||
|
RAYCAST_PRECISION = 0.01
|
||||||
self.location = bpy.context.scene.cursor.location
|
self.location = bpy.context.scene.cursor.location
|
||||||
if self.collection:
|
if self.collection:
|
||||||
for sibling_obj in self.collection.objects:
|
for sibling_obj in self.collection.objects:
|
||||||
@@ -541,24 +542,41 @@ class DumbWallGenerator:
|
|||||||
continue
|
continue
|
||||||
if "IfcWall" not in sibling_obj.name:
|
if "IfcWall" not in sibling_obj.name:
|
||||||
continue
|
continue
|
||||||
local_location = sibling_obj.matrix_world.inverted() @ self.location
|
inv_obj_matrix = sibling_obj.matrix_world.inverted()
|
||||||
|
local_location = inv_obj_matrix @ self.location
|
||||||
try:
|
try:
|
||||||
raycast = sibling_obj.closest_point_on_mesh(local_location, distance=0.01)
|
raycast = sibling_obj.closest_point_on_mesh(local_location, distance=RAYCAST_PRECISION)
|
||||||
except:
|
except:
|
||||||
# If the mesh has no faces
|
# If the mesh has no faces
|
||||||
raycast = [None]
|
raycast = [None]
|
||||||
if not raycast[0]:
|
if not raycast[0]:
|
||||||
continue
|
continue
|
||||||
for face in sibling_obj.data.polygons:
|
for face in sibling_obj.data.polygons:
|
||||||
if (
|
normal = (sibling_obj.matrix_world.to_quaternion() @ face.normal).normalized()
|
||||||
abs(face.normal.y) >= 0.75
|
face_center = sibling_obj.matrix_world @ face.center
|
||||||
and abs(mathutils.geometry.distance_point_to_plane(local_location, face.center, face.normal))
|
if normal.z != 0 or abs(mathutils.geometry.distance_point_to_plane(self.location, face_center, normal)) > 0.01:
|
||||||
< 0.01
|
continue
|
||||||
):
|
|
||||||
# Rotate the wall in the direction of the face normal
|
rotation = math.atan2(normal[1], normal[0])
|
||||||
normal = (sibling_obj.matrix_world.to_quaternion() @ face.normal).normalized()
|
rotated_y_axis = Matrix.Rotation(-rotation, 4, "Z")[1].xyz
|
||||||
self.rotation = math.atan2(normal[1], normal[0])
|
|
||||||
break
|
# since wall thickness goes by local Y+ axis
|
||||||
|
# we find best position for the next wall
|
||||||
|
# by finding the face of another wall that will be very close to the some test point.
|
||||||
|
# test point is calculated by applying to cursor position some little offset along the face
|
||||||
|
#
|
||||||
|
# a bit different offset to be safe on raycast
|
||||||
|
test_pos = self.location + rotated_y_axis * RAYCAST_PRECISION * 1.1
|
||||||
|
test_pos_local = inv_obj_matrix @ test_pos
|
||||||
|
raycast = sibling_obj.closest_point_on_mesh(test_pos_local, distance=RAYCAST_PRECISION)
|
||||||
|
|
||||||
|
if not raycast[0]:
|
||||||
|
continue
|
||||||
|
self.rotation = rotation
|
||||||
|
break
|
||||||
|
|
||||||
|
if self.rotation != 0:
|
||||||
|
break
|
||||||
return self.create_wall()
|
return self.create_wall()
|
||||||
|
|
||||||
def create_wall(self):
|
def create_wall(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user