Basic polyline implementation

This commit is contained in:
Bruno Perdigão
2024-07-30 19:35:19 -03:00
committed by Bruno Perdigão
parent 056df7758b
commit 10035662dd
7 changed files with 151 additions and 27 deletions
@@ -117,7 +117,8 @@ classes = (
space.ToggleHideSpaces,
mep.FitFlowSegments,
mep.RegenerateDistributionElement,
prop.SnapVertex,
prop.SnapMousePoint,
prop.PolylinePoint,
prop.BIMModelProperties,
prop.BIMArrayProperties,
prop.BIMStairProperties,
@@ -337,9 +337,26 @@ class WallPolylineDecorator:
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
gpu.state.point_size_set(10)
snap_prop = context.scene.BIMModelProperties.snap_vertex[0]
points = [Vector((snap_prop.x, snap_prop.y, snap_prop.z))]
snap_prop = context.scene.BIMModelProperties.snap_mouse_point[0]
point = [Vector((snap_prop.x, snap_prop.y, snap_prop.z))]
if snap_prop.snap_type in ["Face", "Plane"]:
self.draw_batch("POINTS", points, decorator_color_special)
self.draw_batch("POINTS", point, decorator_color_special)
else:
self.draw_batch("POINTS", points, decorator_color_selected)
self.draw_batch("POINTS", point, decorator_color_selected)
polyline_data = context.scene.BIMModelProperties.polyline_point
polyline_points = []
polyline_edges = []
for point_prop in polyline_data:
point = Vector((point_prop.x, point_prop.y, point_prop.z))
polyline_points.append(point)
for i in range(len(polyline_points) - 1):
polyline_edges.append([i, i+1])
self.draw_batch("POINTS", polyline_points, decorator_color_selected)
if len(polyline_points) > 1:
self.draw_batch("LINES", polyline_points, decorator_color_selected, polyline_edges)
self.line_shader.uniform_float("lineWidth", 2.0)
@@ -99,11 +99,16 @@ def is_object_array_applicable(self, obj):
return ifcopenshell.util.element.get_pset(element, "BBIM_Array")
class SnapVertex(PropertyGroup):
class SnapMousePoint(PropertyGroup):
x: bpy.props.FloatProperty(name="X")
y: bpy.props.FloatProperty(name="Y")
z: bpy.props.FloatProperty(name="Z")
snap_type: bpy.props.StringProperty(name="Snap Type")
class PolylinePoint(PropertyGroup):
x: bpy.props.FloatProperty(name="X")
y: bpy.props.FloatProperty(name="Y")
z: bpy.props.FloatProperty(name="Z")
class BIMModelProperties(PropertyGroup):
@@ -197,7 +202,8 @@ class BIMModelProperties(PropertyGroup):
type_predefined_type: bpy.props.EnumProperty(items=get_type_predefined_type, name="Predefined Type", default=None)
type_name: bpy.props.StringProperty(name="Name", default="TYPEX")
boundary_class: bpy.props.EnumProperty(items=get_boundary_class, name="Boundary Class")
snap_vertex: bpy.props.CollectionProperty(type=SnapVertex)
snap_mouse_point: bpy.props.CollectionProperty(type=SnapMousePoint)
polyline_point: bpy.props.CollectionProperty(type=PolylinePoint)
class BIMArrayProperties(PropertyGroup):
@@ -338,7 +338,7 @@ class DrawPolylineWall(bpy.types.Operator):
return (obj, bbox_2d)
def main(self, context, event):
def snaping_movement(self, context, event):
scene = context.scene
region = context.region
rv3d = context.region_data
@@ -506,35 +506,27 @@ class DrawPolylineWall(bpy.types.Operator):
obj, hit, face_index = cast_rays_and_get_best_object()
intersection = ray_cast_to_plane(context, plane_origin, plane_normal)
try:
snap_vertex = context.scene.BIMModelProperties.snap_vertex[0]
except:
snap_vertex = context.scene.BIMModelProperties.snap_vertex.add()
if obj is not None:
original_obj = obj.original
snap_points = get_snap_points(obj, face_index)
snap_point = select_snap_point(snap_points, hit, snap_threshold)
snap_points = tool.Snaping.get_snap_points_on_raycasted_obj(obj, face_index)
snap_point = tool.Snaping.select_snap_point(snap_points, hit, snap_threshold)
if snap_point:
snap_vertex.x = snap_point[0][0]
snap_vertex.y = snap_point[0][1]
snap_vertex.z = snap_point[0][2]
snap_vertex.snap_type = snap_point[1]
tool.Snaping.update_snaping_point(snap_point[0], snap_point[1])
else:
snap_vertex.x = hit[0]
snap_vertex.y = hit[1]
snap_vertex.z = hit[2]
snap_vertex.snap_type = "Face"
tool.Snaping.update_snaping_point(hit, "Face")
else:
snap_vertex.x = intersection[0]
snap_vertex.y = intersection[1]
snap_vertex.z = intersection[2]
snap_vertex.snap_type = "Plane"
tool.Snaping.update_snaping_point(intersection, "Plane")
def draw_polyline(self, context):
tool.Snaping.insert_polyline_point()
def modal(self, context, event):
if event.type == 'MOUSEMOVE':
@@ -551,16 +543,20 @@ class DrawPolylineWall(bpy.types.Operator):
if self.mousemove_count > 3:
start_time = time()
self.main(context, event)
self.snaping_movement(context, event)
operator_time = time() - start_time
print(f"main function was finished in {operator_time:.2f} seconds")
return {'RUNNING_MODAL'}
if event.type == 'LEFTMOUSE':
self.draw_polyline(context)
if event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
return {'PASS_THROUGH'}
if event.type in {'RIGHTMOUSE', 'ESC'}:
WallPolylineDecorator.uninstall()
tool.Snaping.clear_polyline()
tool.Blender.update_viewport()
print("CANCELLED")
return {'CANCELLED'}
+4
View File
@@ -934,6 +934,10 @@ class Spatial:
class Covering:
def get_z_from_ceiling_height(cls): pass
@interface
class Snaping:
pass
@interface
class Structural:
def disable_editing_structural_analysis_model(cls): pass
@@ -50,6 +50,7 @@ from blenderbim.tool.qto import Qto
from blenderbim.tool.resource import Resource
from blenderbim.tool.root import Root
from blenderbim.tool.sequence import Sequence
from blenderbim.tool.snaping import Snaping
from blenderbim.tool.spatial import Spatial
from blenderbim.tool.covering import Covering
from blenderbim.tool.structural import Structural
+99
View File
@@ -0,0 +1,99 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Cyril Waechter <cyril@biminsight.ch>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import blenderbim.core.tool
import mathutils
from mathutils import Matrix, Vector
class Snaping(blenderbim.core.tool.Snaping):
@classmethod
def get_snap_points_on_raycasted_obj(cls, obj, face_index):
snap_points = {}
matrix = obj.matrix_world.copy()
face = obj.data.polygons[face_index]
vertices = []
for i in face.vertices:
vertices.append(matrix @ obj.data.vertices[i].co)
edges_center = []
for v1, v2 in zip(vertices, vertices[1:] + [vertices[0]]):
middle_dist = (v2-v1) / 2
edges_center.append(v1 + middle_dist)
snap_points.update({tuple(vertex): "Vertices" for vertex in vertices})
snap_points.update({tuple(edge_center): "Edge Center" for edge_center in edges_center})
return snap_points
@classmethod
def select_snap_point(cls, snap_points, hit, threshold):
shortest_distance = None
snap_point = None
for point, snap_type in snap_points.items():
point = Vector(point)
distance = (point - hit).length
if distance > threshold:
continue
if shortest_distance and distance < shortest_distance:
shortest_distance = distance
snap_point = (point, snap_type)
elif not shortest_distance:
shortest_distance = distance
snap_point = (point, snap_type)
else:
pass
return snap_point
@classmethod
def update_snaping_point(cls, snap_point, snap_type):
try:
snap_vertex = bpy.context.scene.BIMModelProperties.snap_mouse_point[0]
except:
snap_vertex = bpy.context.scene.BIMModelProperties.snap_mouse_point.add()
snap_vertex.x = snap_point[0]
snap_vertex.y = snap_point[1]
snap_vertex.z = snap_point[2]
snap_vertex.snap_type = snap_type
@classmethod
def insert_polyline_point(cls):
snap_vertex = bpy.context.scene.BIMModelProperties.snap_mouse_point[0]
polyline_data = bpy.context.scene.BIMModelProperties.polyline_point
print(len(polyline_data))
if len(polyline_data) > 0:
print("X", snap_vertex.x, polyline_data[-1].x)
if snap_vertex.x == polyline_data[-1].x and\
snap_vertex.y == polyline_data[-1].y and\
snap_vertex.z == polyline_data[-1].z:
return
polyline_point = bpy.context.scene.BIMModelProperties.polyline_point.add()
polyline_point.x = snap_vertex.x
polyline_point.y = snap_vertex.y
polyline_point.z = 0 # TODO Update to the the default container height
@classmethod
def clear_polyline(cls):
bpy.context.scene.BIMModelProperties.polyline_point.clear()