- Fixed 2d sketch with transfrom

This commit is contained in:
bklronin
2024-07-16 18:02:27 +02:00
parent 0c3e4eeb5e
commit c6f48a6e78
7 changed files with 273 additions and 200 deletions

View File

@@ -15,6 +15,7 @@ class VTKWidget(QtWidgets.QWidget):
super().__init__(parent)
self.access_selected_points = []
self.selected_normal = None
self.centroid = None
self.selected_edges = []
self.cell_normals = None
@@ -26,6 +27,7 @@ class VTKWidget(QtWidgets.QWidget):
self.picked_edge_actors = []
self.displayed_normal_actors = []
self.body_actors_orig = []
self.flip_toggle = False
@@ -102,6 +104,54 @@ class VTKWidget(QtWidgets.QWidget):
self.interactor.Initialize()
self.interactor.Start()
# Create the grid
grid = self.create_grid(size=100, spacing=10)
# Setup actor and mapper
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(grid)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(0.5, 0.5, 0.5) # Set grid color to gray
self.renderer.AddActor(actor)
def create_grid(self, size=100, spacing=10):
# Create a vtkPoints object and store the points in it
points = vtk.vtkPoints()
# Create lines
lines = vtk.vtkCellArray()
# Create the grid
for i in range(-size, size + 1, spacing):
# X-direction line
points.InsertNextPoint(i, -size, 0)
points.InsertNextPoint(i, size, 0)
line = vtk.vtkLine()
line.GetPointIds().SetId(0, points.GetNumberOfPoints() - 2)
line.GetPointIds().SetId(1, points.GetNumberOfPoints() - 1)
lines.InsertNextCell(line)
# Y-direction line
points.InsertNextPoint(-size, i, 0)
points.InsertNextPoint(size, i, 0)
line = vtk.vtkLine()
line.GetPointIds().SetId(0, points.GetNumberOfPoints() - 2)
line.GetPointIds().SetId(1, points.GetNumberOfPoints() - 1)
lines.InsertNextCell(line)
# Create a polydata to store everything in
grid = vtk.vtkPolyData()
# Add the points to the dataset
grid.SetPoints(points)
# Add the lines to the dataset
grid.SetLines(lines)
return grid
def on_receive_command(self, command):
"""Calls the individual commands pressed in main"""
print("Receive command: ", command)
@@ -147,7 +197,7 @@ class VTKWidget(QtWidgets.QWidget):
# Create a transform for mirroring across the y-axis
mirror_transform = vtk.vtkTransform()
if self.local_matrix:
"""if self.local_matrix:
print(self.local_matrix)
matrix = vtk.vtkMatrix4x4()
matrix.DeepCopy(self.local_matrix)
@@ -156,8 +206,7 @@ class VTKWidget(QtWidgets.QWidget):
mirror_transform.Scale(-1, -1, 1) # Inverting the original mirror look down
else:
pass
#mirror_transform.Scale(1, -1, 1) # This mirrors across the y-axis
mirror_transform.Scale(1, 1, 1) # This mirrors across the y-axis"""
# Apply the transform to the polydata
transformFilter = vtk.vtkTransformPolyDataFilter()
@@ -172,7 +221,7 @@ class VTKWidget(QtWidgets.QWidget):
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(1.0, 1.0, 1.0)
actor.GetProperty().SetLineWidth(2) # Set line width
actor.GetProperty().SetLineWidth(4) # Set line width
# Add the actor to the scene
self.renderer.AddActor(actor)
@@ -180,8 +229,9 @@ class VTKWidget(QtWidgets.QWidget):
mapper.Update()
self.vtk_widget.GetRenderWindow().Render()
def render_from_points_direct_with_faces(self, vertices, faces, color=(0.1, 0.2, 0.8), line_width=2, point_size=5):
"""Sketch Widget has inverted Y axiis therefore we invert y via scale here until fix"""
points = vtk.vtkPoints()
# Use SetData with numpy array
@@ -209,32 +259,11 @@ class VTKWidget(QtWidgets.QWidget):
normalGenerator.ComputeCellNormalsOn()
normalGenerator.Update()
# Create a transform for mirroring across the y-axis
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)
matrix.Invert()
mirror_transform.SetMatrix(matrix)
mirror_transform.Scale(-1, 1, 1) #Inverting the original mirror look down
else:
mirror_transform.Scale(1, -1, 1) # This mirrors across the y-axis
# Apply the transform to the polydata
transformFilter = vtk.vtkTransformPolyDataFilter()
transformFilter.SetInputData(polydata)
transformFilter.SetTransform(mirror_transform)
transformFilter.Update()
self.cell_normals = vtk_to_numpy(normalGenerator.GetOutput().GetCellData().GetNormals())
# Create a mapper and actor
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(transformFilter.GetOutput())
mapper.SetInputData(polydata)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
@@ -243,8 +272,13 @@ class VTKWidget(QtWidgets.QWidget):
actor.GetProperty().SetLineWidth(line_width)
self.renderer.AddActor(actor)
self.body_actors_orig.append(actor)
self.vtk_widget.GetRenderWindow().Render()
def clear_body_actors(self):
for actor in self.body_actors_orig:
self.renderer.RemoveActor(actor)
def visualize_matrix(self, matrix):
points = vtk.vtkPoints()
for i in range(4):
@@ -277,40 +311,6 @@ class VTKWidget(QtWidgets.QWidget):
return vtk_array
def load_custom_mesh(self, vertices, faces):
### Load meshes by own module
# Create a vtkPoints object and store the points in it
points = vtk.vtkPoints()
for vertex in vertices:
points.InsertNextPoint(vertex)
# Create a vtkCellArray to store the faces
cells = vtk.vtkCellArray()
for face in faces:
triangle = vtk.vtkTriangle()
triangle.GetPointIds().SetId(0, face[0])
triangle.GetPointIds().SetId(1, face[1])
triangle.GetPointIds().SetId(2, face[2])
cells.InsertNextCell(triangle)
# Create a polydata object
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
polydata.SetPolys(cells)
# Create mapper and actor
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(polydata) # Make sure this line is present
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# Add to renderer
self.renderer.AddActor(actor)
# Force an update of the pipeline
mapper.Update()
self.vtk_widget.GetRenderWindow().Render()
def get_points_and_edges_from_polydata(self, polydata) -> list:
# Extract points
points = {}
@@ -353,7 +353,7 @@ class VTKWidget(QtWidgets.QWidget):
center_of_mass.SetInputData(projected_mesh)
center_of_mass.SetUseScalarsAsWeights(False)
center_of_mass.Update()
centroid = center_of_mass.GetCenter()
centroid = np.array(center_of_mass.GetCenter())
# Create a coordinate system on the plane
z_axis = np.array(normal)
@@ -363,68 +363,33 @@ class VTKWidget(QtWidgets.QWidget):
x_axis = x_axis / np.linalg.norm(x_axis)
y_axis = np.cross(z_axis, x_axis)
# Create transformation matrix
matrix = vtk.vtkMatrix4x4()
for i in range(3):
matrix.SetElement(i, 0, x_axis[i])
matrix.SetElement(i, 1, y_axis[i])
matrix.SetElement(i, 2, z_axis[i])
matrix.SetElement(i, 3, centroid[i])
self.local_matrix = matrix
matrix.Invert()
# Create rotation matrix (3x3)
rotation_matrix = np.column_stack((x_axis, y_axis, z_axis))
# Store the full transformation for later use if needed
full_transform = np.eye(4)
full_transform[:3, :3] = rotation_matrix
full_transform[:3, 3] = centroid
self.local_matrix = full_transform
# Transform points to 2D coordinates
transform = vtk.vtkTransform()
transform.SetMatrix(matrix)
transform.Scale([1,1,1])
transformer = vtk.vtkTransformPolyDataFilter()
transformer.SetInputData(projected_mesh)
transformer.SetTransform(transform)
transformer.Update()
transformed_mesh = transformer.GetOutput()
points = transformed_mesh.GetPoints()
points = projected_mesh.GetPoints()
xy_coordinates = []
for i in range(points.GetNumberOfPoints()):
point = points.GetPoint(i)
xy_coordinates.append((-point[0], point[1]))
point = np.array(points.GetPoint(i))
# Translate point to origin
point_centered = point - centroid
# Rotate point
rotated_point = np.dot(rotation_matrix.T, point_centered)
# Store only x and y coordinates
xy_coordinates.append((rotated_point[0], rotated_point[1]))
return xy_coordinates
def create_normal_gizmo(self, normal, scale=1.0):
# Normalize the normal vector
normal = np.array(normal)
normal = normal / np.linalg.norm(normal)
# Create an arrow source
arrow_source = vtk.vtkArrowSource()
arrow_source.SetTipResolution(20)
arrow_source.SetShaftResolution(20)
# Create a transform to orient and position the arrow
transform = vtk.vtkTransform()
# Translate to the origin point
transform.SetMatrix(self.local_matrix)
# Apply the transform to the arrow
transform_filter = vtk.vtkTransformPolyDataFilter()
transform_filter.SetInputConnection(arrow_source.GetOutputPort())
transform_filter.SetTransform(transform)
transform_filter.Update()
# Create mapper and actor
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(transform_filter.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(1, 0, 0) # Red color for the arrow
return actor
def add_normal_line(self, origin, normal, length=10.0, color=(1, 0, 0)):
# Normalize the normal vector
normal = np.array(normal)
@@ -520,7 +485,7 @@ class VTKWidget(QtWidgets.QWidget):
edge_actor = vtk.vtkActor()
edge_actor.SetMapper(edge_mapper)
edge_actor.GetProperty().SetColor(1.0, 0.0, 0.0) # Red color for picked edges
edge_actor.GetProperty().SetLineWidth(4) # Make the line thicker
edge_actor.GetProperty().SetLineWidth(8) # Make the line thicker
# Add the actor to the renderer and store it
self.renderer.AddActor(edge_actor)
@@ -530,9 +495,18 @@ class VTKWidget(QtWidgets.QWidget):
self.compute_projection(False)
elif len(self.selected_edges) > 2:
del self.selected_edges[0]
pass
def clear_edge_select(self, ):
def find_origin_vertex(self, edge1, edge2):
if edge1[0] == edge2[0]or edge1[0] == edge2[1]:
return edge1[0]
elif edge1[1] == edge2[0] or edge1[1] == edge2[1]:
return edge1[1]
else:
return None # The edges don't share a vertex
def clear_edge_select(self ):
# Clear selection after projection was succesful
self.selected_edges = []
self.selected_normal = []
@@ -559,21 +533,22 @@ class VTKWidget(QtWidgets.QWidget):
else:
self.selected_normal = selected_normal
centroid = np.mean([point for edge in self.selected_edges for point in edge], axis=0)
self.centroid = np.mean([point for edge in self.selected_edges for point in edge], axis=0)
#self.centroid = self.find_origin_vertex(edge1, edge2)
# 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,
normal_actor = self.add_normal_line(self.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_polydata = self.project_mesh_to_plane(polydata, self.selected_normal, self.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)
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