mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-16 02:24:30 +00:00
Changed input validantion to Snap tool
This commit is contained in:
committed by
Bruno Perdigão
parent
d1d9db3ed8
commit
b137197586
@@ -21,7 +21,7 @@ import gpu
|
||||
import gpu_extras
|
||||
import bmesh
|
||||
import bonsai.tool as tool
|
||||
from math import sin, cos, radians
|
||||
from math import sin, cos, radians, degrees, atan2, acos
|
||||
from bpy.types import SpaceView3D
|
||||
from mathutils import Vector, Matrix
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
@@ -343,12 +343,22 @@ class WallPolylineDecorator:
|
||||
|
||||
@classmethod
|
||||
def calculate_distance_and_angle(cls, context, is_input_on):
|
||||
def calculate_angle(snap_vector, last_point, second_to_last_point):
|
||||
v1 = snap_vector - last_point
|
||||
v2 = last_point - second_to_last_point
|
||||
cos_angle = (v1.dot(v2)) / (v1.length * v2.length)
|
||||
if cos_angle > 1:
|
||||
cos_angle = 1
|
||||
angle = acos(cos_angle)
|
||||
return degrees(angle)
|
||||
|
||||
try:
|
||||
polyline_data = context.scene.BIMModelProperties.polyline_point
|
||||
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
||||
last_point_data = polyline_data[len(polyline_data) - 1]
|
||||
except:
|
||||
last_point_data = None
|
||||
second_to_last_point_data = None
|
||||
default_container_elevation = 0
|
||||
|
||||
snap_prop = context.scene.BIMModelProperties.snap_mouse_point[0]
|
||||
@@ -358,6 +368,11 @@ class WallPolylineDecorator:
|
||||
else:
|
||||
last_point = Vector((0, 0, 0))
|
||||
|
||||
second_to_last_point = None
|
||||
if len(polyline_data) > 1:
|
||||
second_to_last_point_data = polyline_data[len(polyline_data) - 2]
|
||||
second_to_last_point = Vector((second_to_last_point_data.x, second_to_last_point_data.y, second_to_last_point_data.z))
|
||||
|
||||
if is_input_on:
|
||||
snap_vector = Vector(
|
||||
(float(cls.input_panel["X"]), float(cls.input_panel["Y"]), default_container_elevation)
|
||||
@@ -373,12 +388,22 @@ class WallPolylineDecorator:
|
||||
Vector((0, 0)),
|
||||
Vector((1, 0)),
|
||||
)
|
||||
if second_to_last_point:
|
||||
previous_axis = (
|
||||
Vector((second_to_last_point.x, second_to_last_point.y)),
|
||||
Vector((last_point.x, last_point.y)),
|
||||
)
|
||||
else:
|
||||
second_to_last_point = Vector((last_point.x + 10, last_point.y, last_point.z))
|
||||
previous_axis = x_axis_edge
|
||||
|
||||
current_axis = (
|
||||
Vector((last_point.x, last_point.y)),
|
||||
Vector((snap_vector.x, snap_vector.y)),
|
||||
)
|
||||
if distance > 0:
|
||||
angle = tool.Cad.angle_edges(x_axis_edge, current_axis, degrees=True, signed=True)
|
||||
angle = tool.Cad.angle_3_vectors(snap_vector, last_point, second_to_last_point, degrees=True)
|
||||
angle = 180 - angle
|
||||
if cls.input_panel:
|
||||
cls.input_panel["X"] = str(round(snap_vector.x, 4))
|
||||
cls.input_panel["Y"] = str(round(snap_vector.y, 4))
|
||||
@@ -400,11 +425,20 @@ class WallPolylineDecorator:
|
||||
return
|
||||
|
||||
last_point = Vector((last_point_data.x, last_point_data.y, last_point_data.z))
|
||||
second_to_last_point = None
|
||||
if len(polyline_data) > 2:
|
||||
second_to_last_point_data = polyline_data[len(polyline_data) - 2]
|
||||
second_to_last_point = Vector((second_to_last_point_data.x, second_to_last_point_data.y, second_to_last_point_data.z))
|
||||
else:
|
||||
second_to_last_point = Vector((0, 0, 0))
|
||||
|
||||
distance = float(cls.input_panel["D"])
|
||||
|
||||
if distance < 0 or distance > 0:
|
||||
angle_degrees = float(cls.input_panel["A"])
|
||||
angle_radians = radians(360 - angle_degrees) # Substracting from 360 to make it clockwise
|
||||
reference_vector = second_to_last_point - last_point
|
||||
reference_angle = degrees(atan2(reference_vector[1], reference_vector[0]))
|
||||
angle_radians = radians(360 - (angle_degrees - reference_angle)) # Substracting from 360 to make it clockwise
|
||||
x = last_point[0] + distance * cos(angle_radians)
|
||||
y = last_point[1] + distance * sin(angle_radians)
|
||||
if cls.input_panel:
|
||||
@@ -503,11 +537,9 @@ class WallPolylineDecorator:
|
||||
# Line between last polyline point and mouse
|
||||
edges = [[0, 1]]
|
||||
if polyline_points:
|
||||
print("PP", polyline_points)
|
||||
if snap_prop.snap_type != "Plane" and projection_point:
|
||||
self.draw_batch("LINES", [polyline_points[-1]] + projection_point, decorator_color_unselected, edges)
|
||||
else:
|
||||
print("FOI")
|
||||
self.draw_batch("LINES", [polyline_points[-1]] + mouse_point, decorator_color_unselected, edges)
|
||||
|
||||
# Line for angle axis snap
|
||||
|
||||
@@ -285,7 +285,6 @@ class DrawPolylineWall(bpy.types.Operator):
|
||||
bl_label = "Draw Polyline Wall"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.space_data.type == "VIEW_3D"
|
||||
@@ -482,14 +481,18 @@ class DrawPolylineWall(bpy.types.Operator):
|
||||
|
||||
def recalculate_inputs(self, context):
|
||||
if self.number_input:
|
||||
is_valid, self.number_output = self.validate_input(self.number_output)
|
||||
is_valid, self.number_output = tool.Snap.validate_input(self.number_output)
|
||||
self.input_panel[self.input_type] = self.number_output
|
||||
if is_valid:
|
||||
if not is_valid:
|
||||
self.report({"WARNING"}, "The number typed is not valid.")
|
||||
else:
|
||||
if self.input_type in {"X", "Y"}:
|
||||
self.input_panel = WallPolylineDecorator.calculate_distance_and_angle(context, self.is_input_on)
|
||||
elif self.input_type in {"D", "A"}:
|
||||
self.input_panel = WallPolylineDecorator.calculate_x_and_y(context)
|
||||
|
||||
self.input_panel[self.input_type] = self.number_output
|
||||
|
||||
WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type)
|
||||
tool.Blender.update_viewport()
|
||||
|
||||
@@ -509,15 +512,12 @@ class DrawPolylineWall(bpy.types.Operator):
|
||||
relating_type = tool.Ifc.get().by_id(int(relating_type_id))
|
||||
|
||||
walls, is_polyline_closed = DumbWallGenerator(relating_type).generate(True)
|
||||
print(is_polyline_closed)
|
||||
if walls:
|
||||
if is_polyline_closed:
|
||||
for wall1, wall2 in zip(walls, walls[1:] + [walls[0]]):
|
||||
print(wall1["obj"], wall2["obj"])
|
||||
DumbWallJoiner().join_V(wall1["obj"], wall2["obj"])
|
||||
else:
|
||||
for wall1, wall2 in zip(walls[:-1], walls[1:]):
|
||||
print(wall1["obj"], wall2["obj"])
|
||||
DumbWallJoiner().join_V(wall1["obj"], wall2["obj"])
|
||||
|
||||
def modal(self, context, event):
|
||||
@@ -660,7 +660,7 @@ class DrawPolylineWall(bpy.types.Operator):
|
||||
WallPolylineDecorator.install(context)
|
||||
tool.Snap.set_use_default_container(True)
|
||||
WallPolylineDecorator.set_use_default_container(True)
|
||||
tool.Snap.set_snap_plane_method('XY')
|
||||
tool.Snap.set_snap_plane_method("XY")
|
||||
WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type)
|
||||
self.visible_objs = tool.Raycast.get_visible_objects(context)
|
||||
for obj in self.visible_objs:
|
||||
|
||||
@@ -23,6 +23,7 @@ from bonsai.bim.module.model.decorator import WallPolylineDecorator
|
||||
import math
|
||||
import mathutils
|
||||
from mathutils import Matrix, Vector
|
||||
from lark import Lark, Transformer
|
||||
|
||||
|
||||
class Snap(bonsai.core.tool.Snap):
|
||||
@@ -327,3 +328,52 @@ class Snap(bonsai.core.tool.Snap):
|
||||
cls.update_snaping_point(rot_intersection, "Axis")
|
||||
else:
|
||||
cls.update_snaping_point(intersection, "Plane")
|
||||
|
||||
|
||||
@classmethod
|
||||
def validate_input(cls, input_number):
|
||||
grammar = """
|
||||
start: dim expr?
|
||||
dim: NUMBER
|
||||
expr: (ADD | SUB | MUL | DIV) NUMBER
|
||||
|
||||
NUMBER: /-?\\d+(?:\\.\\d+)?/
|
||||
ADD: "+"
|
||||
SUB: "-"
|
||||
MUL: "*"
|
||||
DIV: "/"
|
||||
|
||||
%ignore " "
|
||||
"""
|
||||
|
||||
class InputTransform(Transformer):
|
||||
def dim(self, args):
|
||||
return float(args[0])
|
||||
|
||||
def expr(self, args):
|
||||
op = args[0]
|
||||
value = float(args[1])
|
||||
if op == "+":
|
||||
return lambda x: x + value
|
||||
elif op == "-":
|
||||
return lambda x: x - value
|
||||
elif op == "*":
|
||||
return lambda x: x * value
|
||||
elif op == "/":
|
||||
return lambda x: x / value
|
||||
|
||||
def start(self, args):
|
||||
dimension = args[0]
|
||||
if len(args) > 1:
|
||||
expression = args[1]
|
||||
return expression(dimension)
|
||||
else:
|
||||
return dimension
|
||||
|
||||
try:
|
||||
parser = Lark(grammar, parser="lalr", transformer=InputTransform())
|
||||
result = parser.parse(input_number)
|
||||
return True, str(result)
|
||||
except:
|
||||
return False, "0"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user