Polyline tool - properties refactor.

Better separation of insertion polyline and measurement polyline
This commit is contained in:
Bruno Perdigão
2024-10-05 11:12:03 -03:00
parent b057f89459
commit 2ea4fc6491
9 changed files with 113 additions and 85 deletions
@@ -119,7 +119,7 @@ classes = (
mep.RegenerateDistributionElement,
prop.SnapMousePoint,
prop.PolylinePoint,
prop.MeasurePolyline,
prop.Polyline,
prop.BIMModelProperties,
prop.BIMArrayProperties,
prop.BIMStairProperties,
+29 -25
View File
@@ -355,16 +355,17 @@ class PolylineDecorator:
cls.tool_state = tool_state
def calculate_measurement_x_y_and_z(self, context):
measurement_prop = context.scene.BIMPolylineProperties.polyline_points
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if len(polyline_data) > 0 else []
if len(measurement_prop) == 0 or len(measurement_prop) > 2:
if len(polyline_points) == 0 or len(polyline_points) > 2:
return None, None
start = measurement_prop[0]
if len(measurement_prop) == 1:
start = polyline_points[0]
if len(polyline_points) == 1:
end = context.scene.BIMPolylineProperties.snap_mouse_point[0]
else:
end = measurement_prop[1]
end = polyline_points[1]
x_axis = (Vector((start.x, start.y, start.z)), Vector((end.x, start.y, start.z)))
y_axis = (Vector((end.x, start.y, start.z)), Vector((end.x, end.y, start.z)))
@@ -413,7 +414,8 @@ class PolylineDecorator:
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
self.line_shader.uniform_float("lineWidth", 2.0)
decorator_color = self.addon_prefs.decorator_color_special
polyline = context.scene.BIMPolylineProperties.polyline_points
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if len(polyline_data) > 0 else []
prop = context.scene.BIMPolylineProperties.product_preview
points = []
@@ -527,7 +529,8 @@ class PolylineDecorator:
region = context.region
rv3d = region.data
measure_type = context.scene.MeasureToolSettings.measure_type
measurement_prop = context.scene.BIMPolylineProperties.polyline_points
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if len(polyline_data) > 0 else []
self.addon_prefs = tool.Blender.get_addon_preferences()
self.font_id = 1
@@ -539,13 +542,13 @@ class PolylineDecorator:
color = self.addon_prefs.decorations_colour
blf.color(self.font_id, *color)
for i in range(len(measurement_prop)):
for i in range(len(polyline_points)):
if i == 0:
continue
dim_text_pos = (Vector(measurement_prop[i].position) + Vector(measurement_prop[i - 1].position)) / 2
dim_text_pos = (Vector(polyline_points[i].position) + Vector(polyline_points[i - 1].position)) / 2
dim_text_coords = view3d_utils.location_3d_to_region_2d(region, rv3d, dim_text_pos)
formatted_value = measurement_prop[i].dim
formatted_value = polyline_points[i].dim
blf.position(self.font_id, dim_text_coords[0], dim_text_coords[1], 0)
text = "d: " + formatted_value
@@ -555,10 +558,10 @@ class PolylineDecorator:
if i == 1:
continue
angle_text_pos = measurement_prop[i - 1].position
angle_text_pos = polyline_points[i - 1].position
angle_text_coords = view3d_utils.location_3d_to_region_2d(region, rv3d, angle_text_pos)
blf.position(self.font_id, angle_text_coords[0], angle_text_coords[1], 0)
text = "a: " + measurement_prop[i].angle
text = "a: " + polyline_points[i].angle
text_length = blf.dimensions(self.font_id, text)
self.draw_text_background(context, angle_text_coords, text_length)
blf.draw(self.font_id, text)
@@ -673,14 +676,15 @@ class PolylineDecorator:
self.draw_batch("LINES", mouse_point + projection_point, decorator_color_unselected, edges)
# Create polyline with selected points
polyline_data = context.scene.BIMPolylineProperties.polyline_points
polyline_points = []
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if len(polyline_data) > 0 else []
polyline_verts = []
polyline_edges = []
for point_prop in polyline_data:
for point_prop in polyline_points:
point = Vector((point_prop.x, point_prop.y, point_prop.z))
polyline_points.append(point)
polyline_verts.append(point)
for i in range(len(polyline_points) - 1):
for i in range(len(polyline_verts) - 1):
polyline_edges.append([i, i + 1])
# Line for angle axis snap
@@ -718,8 +722,8 @@ class PolylineDecorator:
has_area = False
if has_area:
if self.input_ui.get_number_value("AREA") > 0:
tris = self.calculate_polygon(polyline_points)
self.draw_batch("TRIS", polyline_points, transparent_color(decorator_color_special), tris)
tris = self.calculate_polygon(polyline_verts)
self.draw_batch("TRIS", polyline_verts, transparent_color(decorator_color_special), tris)
# Mouse points
if snap_prop.snap_type in ["Plane", "Axis", "Mix"]:
@@ -728,14 +732,14 @@ class PolylineDecorator:
# Line between last polyline point and mouse
self.line_shader.uniform_float("lineWidth", 2.0)
edges = [[0, 1]]
if polyline_points:
if polyline_verts:
if snap_prop.snap_type != "Plane" and projection_point:
self.draw_batch("LINES", [polyline_points[-1]] + projection_point, decorator_color_selected, edges)
self.draw_batch("LINES", [polyline_verts[-1]] + projection_point, decorator_color_selected, edges)
else:
self.draw_batch("LINES", [polyline_points[-1]] + mouse_point, decorator_color_selected, edges)
self.draw_batch("LINES", [polyline_verts[-1]] + mouse_point, decorator_color_selected, edges)
# Draw polyline with selected points
self.line_shader.uniform_float("lineWidth", 2.0)
self.draw_batch("POINTS", polyline_points, decorator_color_unselected)
if len(polyline_points) > 1:
self.draw_batch("LINES", polyline_points, decorator_color_unselected, polyline_edges)
self.draw_batch("POINTS", polyline_verts, decorator_color_unselected)
if len(polyline_verts) > 1:
self.draw_batch("LINES", polyline_verts, decorator_color_unselected, polyline_edges)
@@ -137,7 +137,7 @@ class AddOccurrence(bpy.types.Operator, PolylineOperator):
except:
pass
point = context.scene.BIMPolylineProperties.polyline_points[0]
point = context.scene.BIMPolylineProperties.insertion_polyline[0].polyline_points[0]
context.scene.cursor.location = Vector((point.x, point.y, point.z))
tool.Snap.clear_polyline()
+3 -3
View File
@@ -750,7 +750,7 @@ class PolylinePoint(PropertyGroup):
position: bpy.props.FloatVectorProperty(name="Decorator Position", size=3)
class MeasurePolyline(PropertyGroup):
class Polyline(PropertyGroup):
polyline_points: bpy.props.CollectionProperty(type=PolylinePoint)
measurement_type: bpy.props.StringProperty(name="Measurement Type")
area: bpy.props.StringProperty(name="Measured Area")
@@ -760,6 +760,6 @@ class MeasurePolyline(PropertyGroup):
class BIMPolylineProperties(PropertyGroup):
snap_mouse_point: bpy.props.CollectionProperty(type=SnapMousePoint)
snap_mouse_ref: bpy.props.CollectionProperty(type=SnapMousePoint)
polyline_points: bpy.props.CollectionProperty(type=PolylinePoint)
insertion_polyline: bpy.props.CollectionProperty(type=Polyline)
product_preview: bpy.props.CollectionProperty(type=PolylinePoint)
measurement_polyline: bpy.props.CollectionProperty(type=MeasurePolyline)
measurement_polyline: bpy.props.CollectionProperty(type=Polyline)
+8 -7
View File
@@ -520,18 +520,19 @@ class DumbWallGenerator:
)
def derive_from_polyline(self):
polyline_data = bpy.context.scene.BIMPolylineProperties.polyline_points
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data.polyline_points
is_polyline_closed = False
if len(polyline_data) > 3:
first_vec = Vector((polyline_data[0].x, polyline_data[0].y, polyline_data[0].z))
last_vec = Vector((polyline_data[-1].x, polyline_data[-1].y, polyline_data[-1].z))
if len(polyline_points) > 3:
first_vec = Vector((polyline_points[0].x, polyline_points[0].y, polyline_points[0].z))
last_vec = Vector((polyline_points[-1].x, polyline_points[-1].y, polyline_points[-1].z))
if first_vec == last_vec:
is_polyline_closed = True
walls = []
for i in range(len(polyline_data) - 1):
vec1 = Vector((polyline_data[i].x, polyline_data[i].y, polyline_data[i].z))
vec2 = Vector((polyline_data[i + 1].x, polyline_data[i + 1].y, polyline_data[i + 1].z))
for i in range(len(polyline_points) - 1):
vec1 = Vector((polyline_points[i].x, polyline_points[i].y, polyline_points[i].z))
vec2 = Vector((polyline_points[i + 1].x, polyline_points[i + 1].y, polyline_points[i + 1].z))
coords = (vec1, vec2)
walls.append(self.create_wall_from_2_points(coords))
return walls, is_polyline_closed
@@ -2380,7 +2380,7 @@ class MeasureTool(bpy.types.Operator, PolylineOperator):
def __init__(self):
super().__init__()
if self.measure_type == 'AREA':
if self.measure_type == "AREA":
self.input_ui = tool.Polyline.create_input_ui(init_z=True, init_area=True)
else:
self.input_ui = tool.Polyline.create_input_ui(init_z=True)
@@ -2411,9 +2411,14 @@ class MeasureTool(bpy.types.Operator, PolylineOperator):
self.handle_snap_selection(context, event)
single_mode = False
if self.measure_type == "SINGLE" and len(context.scene.BIMPolylineProperties.polyline_points) >= 2:
if (
self.measure_type == "SINGLE"
and context.scene.BIMPolylineProperties.insertion_polyline
and len(context.scene.BIMPolylineProperties.insertion_polyline[0].polyline_points) >= 2
):
single_mode = True
if (
not self.tool_state.is_input_on
and event.value == "RELEASE"
+19 -14
View File
@@ -106,10 +106,12 @@ class Polyline(bonsai.core.tool.Polyline):
def calculate_distance_and_angle(cls, context, input_ui, tool_state):
try:
polyline_data = context.scene.BIMPolylineProperties.polyline_points
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
last_point_data = polyline_data[len(polyline_data) - 1]
last_point_data = polyline_points[len(polyline_points) - 1]
except:
polyline_points = []
default_container_elevation = 0
last_point_data = None
@@ -136,8 +138,8 @@ class Polyline(bonsai.core.tool.Polyline):
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
second_to_last_point = None
if len(polyline_data) > 1:
second_to_last_point_data = polyline_data[len(polyline_data) - 2]
if len(polyline_points) > 1:
second_to_last_point_data = polyline_points[len(polyline_points) - 2]
second_to_last_point = Vector(
(second_to_last_point_data.x, second_to_last_point_data.y, second_to_last_point_data.z)
)
@@ -174,15 +176,16 @@ class Polyline(bonsai.core.tool.Polyline):
@classmethod
def calculate_area(cls, context, input_ui):
try:
polyline_data = context.scene.BIMPolylineProperties.polyline_points
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
except:
return input_ui
if len(polyline_data) < 3:
if len(polyline_points) < 3:
return input_ui
points = []
for data in polyline_data:
for data in polyline_points:
points.append(Vector((data.x, data.y, data.z)))
if points[0] == points[-1]:
@@ -217,9 +220,10 @@ class Polyline(bonsai.core.tool.Polyline):
@classmethod
def calculate_x_y_and_z(cls, context, input_ui, tool_state):
try:
polyline_data = context.scene.BIMPolylineProperties.polyline_points
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
last_point_data = polyline_data[len(polyline_data) - 1]
last_point_data = polyline_points[len(polyline_points) - 1]
last_point = Vector((last_point_data.x, last_point_data.y, last_point_data.z))
except:
default_container_elevation = 0
@@ -233,8 +237,8 @@ class Polyline(bonsai.core.tool.Polyline):
else:
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
if len(polyline_data) > 1:
second_to_last_point_data = polyline_data[len(polyline_data) - 2]
if len(polyline_points) > 1:
second_to_last_point_data = polyline_points[len(polyline_points) - 2]
second_to_last_point = Vector(
(second_to_last_point_data.x, second_to_last_point_data.y, second_to_last_point_data.z)
)
@@ -301,11 +305,12 @@ class Polyline(bonsai.core.tool.Polyline):
base_vertices = []
top_vertices = []
polyline_data = context.scene.BIMPolylineProperties.polyline_points
if len(polyline_data) < 2:
polyline_data = context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
if len(polyline_points) < 2:
context.scene.BIMPolylineProperties.product_preview.clear()
return
for point in polyline_data:
for point in polyline_points:
base_vertices.append(Vector((point.x, point.y, point.z)))
is_closed = False
+11 -10
View File
@@ -209,20 +209,21 @@ class Raycast(bonsai.core.tool.Raycast):
except:
loc = Vector((0, 0, 0))
polyline_data = bpy.context.scene.BIMPolylineProperties.polyline_points
polyline_data = polyline_data[
: len(polyline_data) - 1
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
polyline_points = polyline_points[
: len(polyline_points) - 1
] # It doesn't make sense to snap to the last point created
polyline_points = []
for point_data in polyline_data:
point = Vector((point_data.x, point_data.y, point_data.z))
polyline_verts = []
for point_data in polyline_points:
vertex = Vector((point_data.x, point_data.y, point_data.z))
intersection, _ = mathutils.geometry.intersect_point_line(point, ray_target, loc)
distance = (point - intersection).length
intersection, _ = mathutils.geometry.intersect_point_line(vertex, ray_target, loc)
distance = (vertex - intersection).length
if distance < 0.2:
polyline_points.append((point, "Vertex"))
polyline_verts.append((vertex, "Vertex"))
return polyline_points
return polyline_verts
@classmethod
def ray_cast_to_measure(cls, context, event, points):
+33 -21
View File
@@ -112,21 +112,27 @@ class Snap(bonsai.core.tool.Snap):
y = snap_vertex.y
z = snap_vertex.z
polyline_data = bpy.context.scene.BIMPolylineProperties.polyline_points
if polyline_data:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
if not polyline_data:
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline.add()
else:
polyline_data = polyline_data[0]
polyline_points = polyline_data.polyline_points
if polyline_points:
# Avoids creating two points at the same location
for point in polyline_data[1:]: # The first can be repeated to form a wall loop
for point in polyline_points[1:]: # The first can be repeated to form a wall loop
if (x, y, z) == (point.x, point.y, point.z):
return "Cannot create two points at the same location"
# TODO move this limitation to be Wall tool specific. Right now it also affects Measure tool
# Avoids creating segments smaller then 0.1. This is a limitation from create_wall_from_2_points
length = (
Vector((x, y, z)) - Vector((polyline_data[-1].x, polyline_data[-1].y, polyline_data[-1].z))
Vector((x, y, z)) - Vector((polyline_points[-1].x, polyline_points[-1].y, polyline_points[-1].z))
).length
if round(length, 4) < 0.1:
return "Cannot create a segment smaller then 10cm"
polyline_point = bpy.context.scene.BIMPolylineProperties.polyline_points.add()
polyline_point = polyline_points.add()
polyline_point.x = x
polyline_point.y = y
polyline_point.z = z
@@ -137,32 +143,35 @@ class Snap(bonsai.core.tool.Snap):
@classmethod
def close_polyline(cls):
polyline_data = bpy.context.scene.BIMPolylineProperties.polyline_points
if len(polyline_data) > 2:
first_point = polyline_data[0]
last_point = polyline_data[-1]
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if len(polyline_data) > 0 else []
if len(polyline_points) > 2:
first_point = polyline_points[0]
last_point = polyline_points[-1]
if not (first_point.x == last_point.x and first_point.y == last_point.y and first_point.z == last_point.z):
polyline_point = bpy.context.scene.BIMPolylineProperties.polyline_points.add()
polyline_point = polyline_points.add()
polyline_point.x = first_point.x
polyline_point.y = first_point.y
polyline_point.z = first_point.z
@classmethod
def clear_polyline(cls):
bpy.context.scene.BIMPolylineProperties.polyline_points.clear()
bpy.context.scene.BIMPolylineProperties.insertion_polyline.clear()
@classmethod
def remove_last_polyline_point(cls):
polyline_data = bpy.context.scene.BIMPolylineProperties.polyline_points
polyline_data.remove(len(polyline_data) - 1)
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if len(polyline_data) > 0 else []
polyline_points.remove(len(polyline_points) - 1)
@classmethod
def move_polyline_to_measure(cls, context, input_ui):
polyline_data = bpy.context.scene.BIMPolylineProperties.polyline_points
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if len(polyline_data) > 0 else []
measurement_data = bpy.context.scene.BIMPolylineProperties.measurement_polyline.add()
measurement_type = bpy.context.scene.MeasureToolSettings.measure_type
measurement_data.measurement_type = measurement_type
for point in polyline_data:
for point in polyline_points:
measurement_point = measurement_data.polyline_points.add()
measurement_point.x = point.x
measurement_point.y = point.y
@@ -221,9 +230,10 @@ class Snap(bonsai.core.tool.Snap):
return (v1, v2, v3, v4)
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
polyline_data = bpy.context.scene.BIMPolylineProperties.polyline_points
if polyline_data:
last_point_data = polyline_data[-1]
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline
polyline_points = polyline_data[0].polyline_points if len(polyline_data) > 0 else []
if polyline_points:
last_point_data = polyline_points[-1]
last_point = Vector((last_point_data.x, last_point_data.y, last_point_data.z))
else:
last_point = Vector((0, 0, default_container_elevation))
@@ -400,11 +410,13 @@ class Snap(bonsai.core.tool.Snap):
detected_snaps.append({"Edge-Vertex": (obj, snap_point)})
# Polyline
try:
polyline_data = bpy.context.scene.BIMPolylineProperties.polyline_points
last_polyline_point = polyline_data[len(polyline_data) - 1]
polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline[0]
polyline_points = polyline_data.polyline_points
last_polyline_point = polyline_points[len(polyline_points) - 1]
except:
polyline_points = []
last_polyline_point = None
if polyline_data:
if polyline_points:
snap_points = tool.Raycast.ray_cast_to_polyline(context, event)
if snap_points:
detected_snaps.append({"Polyline": snap_points})