- Sketch projection and extrude in place working

This commit is contained in:
bklronin
2024-07-13 13:46:13 +02:00
parent d2b8d9540a
commit 0c3e4eeb5e
5 changed files with 726 additions and 494 deletions

View File

@@ -18,11 +18,13 @@ class SketchWidget(QWidget):
def __init__(self):
super().__init__()
self.line_draw_buffer = [None, None]
self.drag_buffer = [None, None]
self.main_buffer = [None, None]
self.proj_snap_points = []
self.proj_snap_lines = []
self.hovered_point = None
self.selected_line = None
@@ -59,7 +61,9 @@ class SketchWidget(QWidget):
for point in lines:
print(point)
x, y = point
self.proj_snap_points = lines
self.proj_snap_lines = lines
self.proj_snap_points.append(QPoint(x, y))
#point = self.solv.add_point_2d(x, y, self.wp)
@@ -311,7 +315,10 @@ class SketchWidget(QWidget):
self.reset_buffers()
if event.button() == Qt.LeftButton and self.mouse_mode == "line":
clicked_pos = local_event_pos
if self.hovered_point:
clicked_pos = self.hovered_point
else:
clicked_pos = local_event_pos
if not self.line_draw_buffer[0]:
self.line_draw_buffer[0] = clicked_pos
@@ -564,6 +571,12 @@ class SketchWidget(QWidget):
closest_point = point['ui_point']
min_distance = distance
for point in self.proj_snap_points:
distance = (local_event_pos - point).manhattanLength()
if distance < threshold and distance < min_distance:
closest_point = point
min_distance = distance
if closest_point != self.hovered_point:
self.hovered_point = closest_point
print(self.hovered_point)
@@ -636,7 +649,7 @@ class SketchWidget(QWidget):
def draw_cross(self, painter, x, y, size=10):
# Set up the pen
pen = QPen(QColor('red')) # You can change the color as needed
pen = QPen(QColor('green')) # You can change the color as needed
pen.setWidth(int(2 / self.zoom)) # Set the line widt)h
painter.setPen(pen)
@@ -712,7 +725,7 @@ class SketchWidget(QWidget):
painter.setPen(QPen(Qt.red, 2))
painter.drawLine(p1, p2)
for cross in self.proj_snap_points:
for cross in self.proj_snap_lines:
# Calculate the endpoints of the cross
self.draw_cross(painter, cross[0], cross[1], 10)

View File

@@ -25,6 +25,9 @@ class VTKWidget(QtWidgets.QWidget):
self.vtk_widget = QVTKRenderWindowInteractor(self)
self.picked_edge_actors = []
self.displayed_normal_actors = []
self.flip_toggle = False
# Create layout and add VTK widget
layout = QtWidgets.QVBoxLayout()
@@ -38,8 +41,26 @@ class VTKWidget(QtWidgets.QWidget):
# Set up the camera
self.camera = self.renderer.GetActiveCamera()
self.camera.SetPosition(5, 5, 100)
self.camera.SetPosition(5, 5, 1000)
self.camera.SetFocalPoint(0, 0, 0)
self.camera.SetClippingRange(0.1, 10000)
# Light Setup
def add_light(renderer, position, color=(1, 1, 1), intensity=1.0):
light = vtk.vtkLight()
light.SetPosition(position)
light.SetColor(color)
light.SetIntensity(intensity)
renderer.AddLight(light)
# Add lights from multiple directions
add_light(self.renderer, (1000, 0, 0), intensity=1.5)
add_light(self.renderer, (-1000, 0, 0), intensity=1.5)
add_light(self.renderer, (0, 1000, 0), intensity=1.5)
add_light(self.renderer, (0, -1000, 0), intensity=1.5)
add_light(self.renderer, (0, 0, 1000), intensity=1.5)
add_light(self.renderer, (0, 0, -1000), intensity=1.5)
# Set up picking
self.picker = vtk.vtkCellPicker()
@@ -81,6 +102,14 @@ class VTKWidget(QtWidgets.QWidget):
self.interactor.Initialize()
self.interactor.Start()
def on_receive_command(self, command):
"""Calls the individual commands pressed in main"""
print("Receive command: ", command)
if command == "flip":
self.clear_actors_projection()
self.flip_toggle = not self.flip_toggle # Toggle the flag
self.on_invert_normal()
@staticmethod
def compute_normal_from_lines(line1, line2):
vec1 = line1[1] - line1[0]
@@ -142,18 +171,17 @@ class VTKWidget(QtWidgets.QWidget):
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(0.0, 0.0, 1.0) # Set color to red
actor.GetProperty().SetColor(1.0, 1.0, 1.0)
actor.GetProperty().SetLineWidth(2) # Set line width
# Add the actor to the scene
self.renderer.AddActor(actor)
#self.renderer.SetBackground(0.1, 0.2, 0.4) # Set background color
mapper.Update()
self.vtk_widget.GetRenderWindow().Render()
def render_from_points_direct_with_faces(self, vertices, faces, color=(1, 1, 1), line_width=2, point_size=5):
def render_from_points_direct_with_faces(self, vertices, faces, color=(0.1, 0.2, 0.8), line_width=2, point_size=5):
points = vtk.vtkPoints()
# Use SetData with numpy array
@@ -185,6 +213,7 @@ class VTKWidget(QtWidgets.QWidget):
mirror_transform = vtk.vtkTransform()
if self.local_matrix:
"""Transforming to the position of the sketch projection with invert matrix"""
print(self.local_matrix)
matrix = vtk.vtkMatrix4x4()
matrix.DeepCopy(self.local_matrix)
@@ -210,7 +239,7 @@ class VTKWidget(QtWidgets.QWidget):
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(color)
actor.GetProperty().EdgeVisibilityOn()
actor.GetProperty().EdgeVisibilityOff()
actor.GetProperty().SetLineWidth(line_width)
self.renderer.AddActor(actor)
@@ -438,6 +467,11 @@ class VTKWidget(QtWidgets.QWidget):
return actor # Return the actor in case you need to remove or modify it later
def on_invert_normal(self):
# Kippstufe für Normal flip
if self.selected_normal is not None:
self.compute_projection(self.flip_toggle)
def on_click(self, obj, event):
click_pos = self.interactor.GetEventPosition()
@@ -468,8 +502,8 @@ class VTKWidget(QtWidgets.QWidget):
point1 = np.array(proj_point1)
point2 = np.array(proj_point2)
print(f"Line starts at: {point1}")
print(f"Line ends at: {point2}")
#print(f"Line starts at: {point1}")
#print(f"Line ends at: {point2}")
# Store this line for later use if needed
self.selected_edges.append((point1, point2))
@@ -493,52 +527,70 @@ class VTKWidget(QtWidgets.QWidget):
self.picked_edge_actors.append(edge_actor)
if len(self.selected_edges) == 2:
# Compute the normal from the two selected edges
edge1 = self.selected_edges[0][1] - self.selected_edges[0][0]
edge2 = self.selected_edges[1][1] - self.selected_edges[1][0]
self.selected_normal = np.cross(edge1, edge2)
self.selected_normal = self.selected_normal / np.linalg.norm(self.selected_normal)
print("Computed normal:", self.selected_normal)
centroid = np.mean([point for edge in self.selected_edges for point in edge], axis=0)
# Draw the normal line
normal_length = 50 # Adjust this value to change the length of the normal line
normal_actor = self.add_normal_line(centroid, self.selected_normal, length=normal_length,
color=(1, 0, 0))
projected_polydata = self.project_mesh_to_plane(polydata, self.selected_normal, centroid)
projected_points = projected_polydata.GetPoints()
print("proj_points", projected_points)
# Extract 2D coordinates
self.project_tosketch_edge = self.compute_2d_coordinates(projected_polydata, self.selected_normal)
print("3d_points_proj", self.project_tosketch_edge)
# Create a mapper and actor for the projected data
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(projected_polydata)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(0.0, 1.0, 0.0) # Set color to green
actor.GetProperty().SetLineWidth(4) # Set line width
self.renderer.AddActor(normal_actor)
# Add the actor to the scene
self.renderer.AddActor(actor)
# Clear selection after
self.selected_edges = []
self.selected_normal = []
for edge_line in self.picked_edge_actors:
self.renderer.RemoveActor(edge_line)
self.compute_projection(False)
elif len(self.selected_edges) > 2:
pass
def clear_edge_select(self, ):
# Clear selection after projection was succesful
self.selected_edges = []
self.selected_normal = []
def clear_actors_projection(self):
"""Removes all actors that were used for projection"""
for edge_line in self.picked_edge_actors:
self.renderer.RemoveActor(edge_line)
for normals in self.displayed_normal_actors:
self.renderer.RemoveActor(normals)
def compute_projection(self, direction_invert: bool= False):
# Compute the normal from the two selected edges )
edge1 = self.selected_edges[0][1] - self.selected_edges[0][0]
edge2 = self.selected_edges[1][1] - self.selected_edges[1][0]
selected_normal = np.cross(edge1, edge2)
selected_normal = selected_normal / np.linalg.norm(selected_normal)
#print("Computed normal:", self.selected_normal)
# Invert the normal in local z if direction_invert is True
if direction_invert:
self.selected_normal = -selected_normal
else:
self.selected_normal = selected_normal
centroid = np.mean([point for edge in self.selected_edges for point in edge], axis=0)
# Draw the normal line
normal_length = 50 # Adjust this value to change the length of the normal line
normal_actor = self.add_normal_line(centroid, self.selected_normal, length=normal_length,
color=(1, 0, 0))
polydata = self.picker.GetActor().GetMapper().GetInput()
projected_polydata = self.project_mesh_to_plane(polydata, self.selected_normal, centroid)
projected_points = projected_polydata.GetPoints()
#print("proj_points", projected_points)
# Extract 2D coordinates
self.project_tosketch_edge = self.compute_2d_coordinates(projected_polydata, self.selected_normal)
#print("3d_points_proj", self.project_tosketch_edge)
# Create a mapper and actor for the projected data
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(projected_polydata)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(0.0, 1.0, 0.0) # Set color to green
actor.GetProperty().SetLineWidth(4) # Set line width
self.renderer.AddActor(normal_actor)
self.displayed_normal_actors.append(normal_actor)
# Add the actor to the scene
self.renderer.AddActor(actor)
self.picked_edge_actors.append(actor)
# Render the scene
self.vtk_widget.GetRenderWindow().Render()