- 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

21
doc/flow.md Normal file
View File

@ -0,0 +1,21 @@
# Signal Flow
## 2D SketchWidget
- 2D QPoint form custom Qpainter widget in linear space
- 2D QPoint ot cartesian space
- 2D tuple into slvspace dict system and solvespace
- get calced position from Solvespace solver
- add to internal reference dict
- Transform to linear QPainter space for display to show
## 3D custom Widget
- Take Tuple points form solvespace main dict
- Draw Interactor and sdfCAD model
### Select and Project
- Project cartesian flattened mesh into 2D
- Transform to 2D xy
- Transform to linear space for 2D widget to draw.
- Result into 2D cartesian for body interaction extrude etc

3
doc/helper_commands.md Normal file
View File

@ -0,0 +1,3 @@
## Compile ui file
pyside6-uic gui.ui > Gui.py -g python

View File

@ -4,14 +4,10 @@ from copy import copy
import numpy as np
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QInputDialog
from PySide6.QtGui import QPainter, QPen, QColor
from PySide6.QtGui import QPainter, QPen, QColor, QTransform
from PySide6.QtCore import Qt, QPoint, QPointF, Signal
from python_solvespace import SolverSystem, ResultFlag
class DrawingTools():
pass
class Costrains():
pass
class SketchWidget(QWidget):
constrain_done = Signal()
@ -59,13 +55,10 @@ class SketchWidget(QWidget):
"""Lines as orientation projected from the sketch"""
for point in lines:
print(point)
x, y = point
self.proj_snap_lines = lines
self.proj_snap_points.append(QPoint(x, y))
#point = self.solv.add_point_2d(x, y, self.wp)
coord = QPoint(x, y)
self.proj_snap_points.append(coord)
"""relation_point = {} # Reinitialize the dictionary
#handle_nr = self.get_handle_nr(str(point))
@ -215,7 +208,6 @@ class SketchWidget(QWidget):
return None
def viewport_to_local_coord(self, qt_pos : QPoint) -> QPoint:
self.to_quadrant_coords(qt_pos)
return QPoint(self.to_quadrant_coords(qt_pos))
def check_all_points(self,) -> list:
@ -647,11 +639,13 @@ class SketchWidget(QWidget):
painter.setPen(QPen(Qt.red, 4))
painter.drawPoint(middle_x, middle_y)
def draw_cross(self, painter, x, y, size=10):
def draw_cross(self, painter, pos: QPoint, size=10):
# Set up the pen
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)
x = pos.x()
y = pos.y()
# Calculate the endpoints of the cross
half_size = size // 2
@ -667,23 +661,47 @@ class SketchWidget(QWidget):
center_x = self.width() // 2
center_y = self.height() // 2
quadrant_x = point.x() - center_x
quadrant_y = point.y() - center_y
quadrant_y = center_y - point.y() # Note the change here
return QPoint(quadrant_x, quadrant_y) / self.zoom
def from_quadrant_coords(self, point: QPoint):
"""Translate quadrant coordinates to linear coordinates."""
center_x = self.width() // 2
center_y = self.height() // 2
widget_x = center_x + point.x() * self.zoom
widget_y = center_y - point.y() * self.zoom # Note the subtraction here
return QPoint(int(widget_x), int(widget_y))
def from_quadrant_coords_no_center(self, point):
"""Translate quadrant coordinates to linear coordinates."""
center_x = 0
center_y = 0
widget_x = center_x + point.x() * self.zoom
widget_y = center_y - point.y() * self.zoom # Note the subtraction here
return QPoint(int(widget_x), int(widget_y))
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
self.drawAxes(painter)
# Create a QTransform object
transform = QTransform()
# Translate the origin to the center of the widget
center = QPoint(self.width() // 2, self.height() // 2)
painter.translate(center)
center = QPointF(self.width() / 2, self.height() / 2)
transform.translate(center.x(), center.y())
# Apply the zoom factor
painter.scale(self.zoom, self.zoom)
transform.scale(self.zoom, -self.zoom) # Negative y-scale to invert y-axis
# Set the transform to the painter
painter.setTransform(transform)
pen = QPen(Qt.gray)
pen.setWidth(2 / self.zoom)
pen.setWidthF(2 / self.zoom)
painter.setPen(pen)
# Draw points
@ -700,36 +718,33 @@ class SketchWidget(QWidget):
painter.drawText(mid, str(round(dis, 2)))
pen = QPen(Qt.green)
pen.setWidth(2)
pen.setWidthF(2 / self.zoom)
painter.setPen(pen)
if self.solv.entity_len():
for i in range(self.solv.entity_len()):
# 3 Entitys in the beginning of the workplane normal and point
entity = self.solv.entity(i)
if entity.is_point_2d() and self.solv.params(entity.params):
x, y = self.solv.params(entity.params)
point = QPoint(x, y)
point = QPointF(x, y)
painter.drawEllipse(point, 6 / self.zoom, 6 / self.zoom)
#Highlight point hovered
# Highlight point hovered
if self.hovered_point:
highlight_pen = QPen(QColor(255, 0, 0))
highlight_pen.setWidth(2)
highlight_pen.setWidthF(2 / self.zoom)
painter.setPen(highlight_pen)
painter.drawEllipse(self.hovered_point, 5 / self.zoom, 5 / self.zoom)
# Highlight line hovered
if self.selected_line and not self.hovered_point:
p1, p2 = self.selected_line
painter.setPen(QPen(Qt.red, 2))
painter.setPen(QPen(Qt.red, 2 / self.zoom))
painter.drawLine(p1, p2)
for cross in self.proj_snap_lines:
# Calculate the endpoints of the cross
self.draw_cross(painter, cross[0], cross[1], 10)
for cross in self.proj_snap_points:
self.draw_cross(painter, cross, 10 / self.zoom)
# self.drawBackgroundGrid(painter)
painter.end()
def wheelEvent(self, event):

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

127
main.py
View File

@ -1,3 +1,8 @@
# nuitka-project: --plugin-enable=pyside6
# nuitka-project: --plugin-enable=numpy
# nuitka-project: --standalone
# nuitka-project: --macos-create-app-bundle
import uuid
import names
from PySide6.QtCore import Qt, QPoint, Signal
@ -12,6 +17,7 @@ from mesh_modules import simple_mesh, vesta_mesh, interactor_mesh
# main, draw_widget, gl_widget
class ExtrudeDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
@ -30,6 +36,7 @@ class ExtrudeDialog(QDialog):
# Symmetric checkbox
self.symmetric_checkbox = QCheckBox('Symmetric Extrude')
self.invert_checkbox = QCheckBox('Invert Extrusion')
# OK and Cancel buttons
button_layout = QHBoxLayout()
@ -43,12 +50,16 @@ class ExtrudeDialog(QDialog):
# Add all widgets to main layout
layout.addLayout(length_layout)
layout.addWidget(self.symmetric_checkbox)
layout.addLayout(length_layout)
layout.addWidget(self.invert_checkbox)
layout.addLayout(button_layout)
self.setLayout(layout)
def get_values(self):
return self.length_input.value(), self.symmetric_checkbox.isChecked()
return self.length_input.value(), self.symmetric_checkbox.isChecked() ,self.invert_checkbox.isChecked()
class MainWindow(QMainWindow):
send_command = Signal(str)
@ -129,7 +140,7 @@ class MainWindow(QMainWindow):
self.sketchWidget.create_proj_lines(edges)
# CLear all selections after it has been projected
self.custom_3D_Widget.clear_edge_select()
#self.custom_3D_Widget.clear_edge_select()
self.custom_3D_Widget.clear_actors_projection()
#self.sketchWidget.create_workplane_space(edges, normal)
@ -189,13 +200,6 @@ class MainWindow(QMainWindow):
self.sketchWidget.mouse_mode = None
self.sketchWidget.reset_buffers()
def calc_sketch_projection_3d(self, lines, z_origin, depth):
print(f"Gemetries {lines}, {z_origin}, {depth}")
edges = interactor_mesh.generate_mesh(lines, z_origin, depth)
print("final_mesh", edges)
self.custom_3D_Widget.load_interactor_mesh(edges)
def draw_mesh(self):
name = self.ui.body_list.currentItem().text()
print("selected_for disp", name)
@ -225,8 +229,10 @@ class MainWindow(QMainWindow):
points_for_interact = []
for point_to_poly in self.sketchWidget.slv_lines_main:
start, end = point_to_poly['ui_points']
start_draw = self.translate_points_tup(start)
end_draw = self.translate_points_tup(end)
from_coord_start = self.sketchWidget.from_quadrant_coords_no_center(start)
from_coord_end = self.sketchWidget.from_quadrant_coords_no_center(end)
start_draw = self.translate_points_tup(from_coord_start)
end_draw = self.translate_points_tup(from_coord_end)
line = start_draw, end_draw
points_for_interact.append(line)
@ -330,9 +336,44 @@ class MainWindow(QMainWindow):
if isinstance(point, QPoint):
return point.x(), point.y()
def rotate_point_to_normal(self, centroid, normal):
# Ensure the normal is a unit vector
normal = normal / np.linalg.norm(normal)
# Initial direction (assuming positive Z-axis)
initial_direction = np.array([0, 0, 1])
# Compute rotation axis
rotation_axis = np.cross(initial_direction, normal)
# If rotation axis is zero (vectors are parallel), no rotation is needed
if np.allclose(rotation_axis, 0):
return centroid
# Compute rotation angle
rotation_angle = np.arccos(np.dot(initial_direction, normal))
# Create rotation matrix using Rodrigues' formula
K = np.array([
[0, -rotation_axis[2], rotation_axis[1]],
[rotation_axis[2], 0, -rotation_axis[0]],
[-rotation_axis[1], rotation_axis[0], 0]
])
rotation_matrix = (
np.eye(3) +
np.sin(rotation_angle) * K +
(1 - np.cos(rotation_angle)) * np.dot(K, K)
)
# Apply rotation to centroid
rotated_centroid = np.dot(rotation_matrix, centroid)
return rotated_centroid
def send_extrude(self):
is_symmetric = None
length = None
invert = None
selected = self.ui.sketch_list.currentItem()
name = selected.text()
points = self.model['sketch'][name]['sketch_points']
@ -342,13 +383,10 @@ class MainWindow(QMainWindow):
#detect loop that causes problems in mesh generation
del points[-1]
"""length, ok = QInputDialog.getDouble(self, 'Extrude Length', 'Enter a mm value:', decimals=2)
#TODO : Implement cancel"""
dialog = ExtrudeDialog(self)
if dialog.exec():
length, is_symmetric = dialog.get_values()
print(f"Extrude length: {length}, Symmetric: {is_symmetric}")
length, is_symmetric, invert = dialog.get_values()
print(f"Extrude length: {length}, Symmetric: {is_symmetric} Invert: {invert}")
else:
length = 0
print("Extrude cancelled")
@ -358,15 +396,31 @@ class MainWindow(QMainWindow):
# Rotation is done in vtk matrix trans
angle = 0
normal = [0, 0, 1]
f = geo.extrude_shape(points, length, angle, normal, is_symmetric)
if not is_symmetric:
origin_z_lvl = length / 2
normal = self.custom_3D_Widget.selected_normal
print("Normie enter", normal)
if normal is None:
normal = [0, 0, 1]
centroid = self.custom_3D_Widget.centroid
if centroid is None:
centroid = [0, 0, 0]
else:
origin_z_lvl = 0
centroid = list(centroid)
print("THis centroid ",centroid)
self.calc_sketch_projection_3d(lines, origin_z_lvl, length)
f = geo.extrude_shape(points, length, angle, normal, centroid, is_symmetric, invert)
z_origin = centroid[2]
if is_symmetric:
z_origin = z_origin - length / 2
if invert:
edges = interactor_mesh.generate_mesh(lines, z_origin, length, True)
else:
edges = interactor_mesh.generate_mesh(lines, z_origin, length, False)
self.custom_3D_Widget.load_interactor_mesh(edges)
name_op = f"extrd-{name}"
element = {
@ -388,7 +442,7 @@ class MainWindow(QMainWindow):
points = self.model['operation'][name]['sdf_object']
self.list_selected.append(points)
if len(self.list_selected) > 1:
if len(self.list_selected) == 2:
geo = Geometry()
f = geo.cut_shapes(self.list_selected[0], self.list_selected[1] )
@ -401,9 +455,12 @@ class MainWindow(QMainWindow):
name_op = f"cut-{name}"
self.model['operation'][name_op] = element
self.ui.body_list.addItem(name_op)
items = self.ui.sketch_list.findItems(name_op, Qt.MatchExactly)
#self.ui.body_list.setCurrentItem(items[-1])
items = self.ui.body_list.findItems(name_op, Qt.MatchExactly)
self.ui.body_list.setCurrentItem(items[-1])
self.custom_3D_Widget.clear_body_actors()
self.draw_mesh()
elif len(self.list_selected) > 2:
self.list_selected.clear()
else:
print("mindestens 2!")
@ -443,16 +500,22 @@ class Geometry:
print("p2", p2)
return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
def extrude_shape(self, points, length: float, angle, normal, symet: bool = True):
def extrude_shape(self, points, length: float, angle, normal, centroid, symet: bool = True, invert: bool = False):
"""2D to 3D sdf always first"""
f = polygon(points).rotate(angle)
f = polygon(points)
f = f.extrude(length)
if not symet:
print("Offsetting", symet)
f = f.extrude(length).orient(normal).translate((0, 0, length/2)) # orient(normal)
# Calculate the offset vector (half the length in the direction of the normal)
offset = [n * (length / 2) for n in normal]
else:
f = f.extrude(length).orient(normal)
# Apply the offset in the direction of the normal
f = f.translate(offset)
# Apply the centroid translation
#f = f.translate(centroid)
# Apply the orientation
f = f.orient(normal)
return f

View File

@ -1,20 +1,18 @@
# Draw simple boundary based on the lines and depth
def generate_mesh(lines: list, z_origin: float, depth: float, symmetric: bool = True):
if symmetric:
depth1 = depth/2
depth2 = -depth/2
origin = create_3D(lines, z_origin, depth1)
extruded = create_3D(lines, z_origin, depth2)
def generate_mesh(lines: list, z_origin: float, depth: float, invert :bool = False):
origin = create_3D(lines, z_origin)
if invert :
extruded = create_3D(lines, z_origin - depth)
else:
origin = create_3D(lines, z_origin, 0)
extruded = create_3D(lines, z_origin, depth)
extruded = create_3D(lines, z_origin + depth)
vert_lines = create_vert_lines(origin, extruded)
print(f"Result = {origin} / {extruded} / {vert_lines}")
return origin + vert_lines + extruded
return origin + vert_lines + extruded
def create_vert_lines(origin, extruded):
@ -26,16 +24,16 @@ def create_vert_lines(origin, extruded):
return vert_lines
def create_3D(lines, z_origin, depth):
def create_3D(lines, z_pos):
line_loop = []
for coordinate2d in lines:
start, end = coordinate2d
xs, ys = start
coordinate3d_start_orig = xs, -ys, z_origin + depth
coordinate3d_start_orig = xs, -ys, z_pos
xe, ye = end
coordinate3d_end_orig = xe, -ye, z_origin + depth
coordinate3d_end_orig = xe, -ye, z_pos
line3d_orig = coordinate3d_start_orig, coordinate3d_end_orig

View File

@ -1,7 +1,5 @@
from sdf import *
c = box(1).translate((0,0,0.2))
f = capped_cylinder(-Z, Z, 0.5)
c.orient([0.5, 0.5, 1])
c = f - c
c.save("out.stl")
f = box(1).translate((1,1,-0.2))
c = hexagon(1).extrude(1).orient([0,0,-1])
c = f & c
f.save("out.stl")