- Fixed 2d sketch with transfrom
This commit is contained in:
parent
0c3e4eeb5e
commit
c6f48a6e78
21
doc/flow.md
Normal file
21
doc/flow.md
Normal 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
3
doc/helper_commands.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
## Compile ui file
|
||||||
|
pyside6-uic gui.ui > Gui.py -g python
|
||||||
|
|
@ -4,14 +4,10 @@ from copy import copy
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QInputDialog
|
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 PySide6.QtCore import Qt, QPoint, QPointF, Signal
|
||||||
from python_solvespace import SolverSystem, ResultFlag
|
from python_solvespace import SolverSystem, ResultFlag
|
||||||
|
|
||||||
class DrawingTools():
|
|
||||||
pass
|
|
||||||
class Costrains():
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SketchWidget(QWidget):
|
class SketchWidget(QWidget):
|
||||||
constrain_done = Signal()
|
constrain_done = Signal()
|
||||||
@ -59,13 +55,10 @@ class SketchWidget(QWidget):
|
|||||||
"""Lines as orientation projected from the sketch"""
|
"""Lines as orientation projected from the sketch"""
|
||||||
|
|
||||||
for point in lines:
|
for point in lines:
|
||||||
print(point)
|
|
||||||
x, y = point
|
x, y = point
|
||||||
self.proj_snap_lines = lines
|
self.proj_snap_lines = lines
|
||||||
self.proj_snap_points.append(QPoint(x, y))
|
coord = QPoint(x, y)
|
||||||
|
self.proj_snap_points.append(coord)
|
||||||
|
|
||||||
#point = self.solv.add_point_2d(x, y, self.wp)
|
|
||||||
|
|
||||||
"""relation_point = {} # Reinitialize the dictionary
|
"""relation_point = {} # Reinitialize the dictionary
|
||||||
#handle_nr = self.get_handle_nr(str(point))
|
#handle_nr = self.get_handle_nr(str(point))
|
||||||
@ -215,7 +208,6 @@ class SketchWidget(QWidget):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def viewport_to_local_coord(self, qt_pos : QPoint) -> QPoint:
|
def viewport_to_local_coord(self, qt_pos : QPoint) -> QPoint:
|
||||||
self.to_quadrant_coords(qt_pos)
|
|
||||||
return QPoint(self.to_quadrant_coords(qt_pos))
|
return QPoint(self.to_quadrant_coords(qt_pos))
|
||||||
|
|
||||||
def check_all_points(self,) -> list:
|
def check_all_points(self,) -> list:
|
||||||
@ -647,11 +639,13 @@ class SketchWidget(QWidget):
|
|||||||
painter.setPen(QPen(Qt.red, 4))
|
painter.setPen(QPen(Qt.red, 4))
|
||||||
painter.drawPoint(middle_x, middle_y)
|
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
|
# Set up the pen
|
||||||
pen = QPen(QColor('green')) # 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
|
pen.setWidth(int(2 / self.zoom)) # Set the line widt)h
|
||||||
painter.setPen(pen)
|
painter.setPen(pen)
|
||||||
|
x = pos.x()
|
||||||
|
y = pos.y()
|
||||||
|
|
||||||
# Calculate the endpoints of the cross
|
# Calculate the endpoints of the cross
|
||||||
half_size = size // 2
|
half_size = size // 2
|
||||||
@ -667,23 +661,47 @@ class SketchWidget(QWidget):
|
|||||||
center_x = self.width() // 2
|
center_x = self.width() // 2
|
||||||
center_y = self.height() // 2
|
center_y = self.height() // 2
|
||||||
quadrant_x = point.x() - center_x
|
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
|
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):
|
def paintEvent(self, event):
|
||||||
painter = QPainter(self)
|
painter = QPainter(self)
|
||||||
|
painter.setRenderHint(QPainter.Antialiasing)
|
||||||
|
|
||||||
self.drawAxes(painter)
|
self.drawAxes(painter)
|
||||||
|
|
||||||
|
# Create a QTransform object
|
||||||
|
transform = QTransform()
|
||||||
|
|
||||||
# Translate the origin to the center of the widget
|
# Translate the origin to the center of the widget
|
||||||
center = QPoint(self.width() // 2, self.height() // 2)
|
center = QPointF(self.width() / 2, self.height() / 2)
|
||||||
painter.translate(center)
|
transform.translate(center.x(), center.y())
|
||||||
|
|
||||||
# Apply the zoom factor
|
# 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 = QPen(Qt.gray)
|
||||||
pen.setWidth(2 / self.zoom)
|
pen.setWidthF(2 / self.zoom)
|
||||||
painter.setPen(pen)
|
painter.setPen(pen)
|
||||||
|
|
||||||
# Draw points
|
# Draw points
|
||||||
@ -700,36 +718,33 @@ class SketchWidget(QWidget):
|
|||||||
painter.drawText(mid, str(round(dis, 2)))
|
painter.drawText(mid, str(round(dis, 2)))
|
||||||
|
|
||||||
pen = QPen(Qt.green)
|
pen = QPen(Qt.green)
|
||||||
pen.setWidth(2)
|
pen.setWidthF(2 / self.zoom)
|
||||||
painter.setPen(pen)
|
painter.setPen(pen)
|
||||||
|
|
||||||
if self.solv.entity_len():
|
if self.solv.entity_len():
|
||||||
for i in range(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)
|
entity = self.solv.entity(i)
|
||||||
if entity.is_point_2d() and self.solv.params(entity.params):
|
if entity.is_point_2d() and self.solv.params(entity.params):
|
||||||
x, y = 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)
|
painter.drawEllipse(point, 6 / self.zoom, 6 / self.zoom)
|
||||||
|
|
||||||
#Highlight point hovered
|
# Highlight point hovered
|
||||||
if self.hovered_point:
|
if self.hovered_point:
|
||||||
highlight_pen = QPen(QColor(255, 0, 0))
|
highlight_pen = QPen(QColor(255, 0, 0))
|
||||||
highlight_pen.setWidth(2)
|
highlight_pen.setWidthF(2 / self.zoom)
|
||||||
painter.setPen(highlight_pen)
|
painter.setPen(highlight_pen)
|
||||||
painter.drawEllipse(self.hovered_point, 5 / self.zoom, 5 / self.zoom)
|
painter.drawEllipse(self.hovered_point, 5 / self.zoom, 5 / self.zoom)
|
||||||
|
|
||||||
# Highlight line hovered
|
# Highlight line hovered
|
||||||
if self.selected_line and not self.hovered_point:
|
if self.selected_line and not self.hovered_point:
|
||||||
p1, p2 = self.selected_line
|
p1, p2 = self.selected_line
|
||||||
painter.setPen(QPen(Qt.red, 2))
|
painter.setPen(QPen(Qt.red, 2 / self.zoom))
|
||||||
painter.drawLine(p1, p2)
|
painter.drawLine(p1, p2)
|
||||||
|
|
||||||
for cross in self.proj_snap_lines:
|
for cross in self.proj_snap_points:
|
||||||
# Calculate the endpoints of the cross
|
self.draw_cross(painter, cross, 10 / self.zoom)
|
||||||
self.draw_cross(painter, cross[0], cross[1], 10)
|
|
||||||
|
|
||||||
# self.drawBackgroundGrid(painter)
|
|
||||||
painter.end()
|
painter.end()
|
||||||
|
|
||||||
def wheelEvent(self, event):
|
def wheelEvent(self, event):
|
||||||
|
@ -15,6 +15,7 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.access_selected_points = []
|
self.access_selected_points = []
|
||||||
self.selected_normal = None
|
self.selected_normal = None
|
||||||
|
self.centroid = None
|
||||||
self.selected_edges = []
|
self.selected_edges = []
|
||||||
self.cell_normals = None
|
self.cell_normals = None
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
|
|
||||||
self.picked_edge_actors = []
|
self.picked_edge_actors = []
|
||||||
self.displayed_normal_actors = []
|
self.displayed_normal_actors = []
|
||||||
|
self.body_actors_orig = []
|
||||||
|
|
||||||
self.flip_toggle = False
|
self.flip_toggle = False
|
||||||
|
|
||||||
@ -102,6 +104,54 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
self.interactor.Initialize()
|
self.interactor.Initialize()
|
||||||
self.interactor.Start()
|
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):
|
def on_receive_command(self, command):
|
||||||
"""Calls the individual commands pressed in main"""
|
"""Calls the individual commands pressed in main"""
|
||||||
print("Receive command: ", command)
|
print("Receive command: ", command)
|
||||||
@ -147,7 +197,7 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
# Create a transform for mirroring across the y-axis
|
# Create a transform for mirroring across the y-axis
|
||||||
mirror_transform = vtk.vtkTransform()
|
mirror_transform = vtk.vtkTransform()
|
||||||
|
|
||||||
if self.local_matrix:
|
"""if self.local_matrix:
|
||||||
print(self.local_matrix)
|
print(self.local_matrix)
|
||||||
matrix = vtk.vtkMatrix4x4()
|
matrix = vtk.vtkMatrix4x4()
|
||||||
matrix.DeepCopy(self.local_matrix)
|
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
|
mirror_transform.Scale(-1, -1, 1) # Inverting the original mirror look down
|
||||||
else:
|
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
|
# Apply the transform to the polydata
|
||||||
transformFilter = vtk.vtkTransformPolyDataFilter()
|
transformFilter = vtk.vtkTransformPolyDataFilter()
|
||||||
@ -172,7 +221,7 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
actor = vtk.vtkActor()
|
actor = vtk.vtkActor()
|
||||||
actor.SetMapper(mapper)
|
actor.SetMapper(mapper)
|
||||||
actor.GetProperty().SetColor(1.0, 1.0, 1.0)
|
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
|
# Add the actor to the scene
|
||||||
self.renderer.AddActor(actor)
|
self.renderer.AddActor(actor)
|
||||||
@ -180,8 +229,9 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
mapper.Update()
|
mapper.Update()
|
||||||
self.vtk_widget.GetRenderWindow().Render()
|
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):
|
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()
|
points = vtk.vtkPoints()
|
||||||
|
|
||||||
# Use SetData with numpy array
|
# Use SetData with numpy array
|
||||||
@ -209,32 +259,11 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
normalGenerator.ComputeCellNormalsOn()
|
normalGenerator.ComputeCellNormalsOn()
|
||||||
normalGenerator.Update()
|
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())
|
self.cell_normals = vtk_to_numpy(normalGenerator.GetOutput().GetCellData().GetNormals())
|
||||||
|
|
||||||
# Create a mapper and actor
|
# Create a mapper and actor
|
||||||
mapper = vtk.vtkPolyDataMapper()
|
mapper = vtk.vtkPolyDataMapper()
|
||||||
mapper.SetInputData(transformFilter.GetOutput())
|
mapper.SetInputData(polydata)
|
||||||
|
|
||||||
actor = vtk.vtkActor()
|
actor = vtk.vtkActor()
|
||||||
actor.SetMapper(mapper)
|
actor.SetMapper(mapper)
|
||||||
@ -243,8 +272,13 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
actor.GetProperty().SetLineWidth(line_width)
|
actor.GetProperty().SetLineWidth(line_width)
|
||||||
|
|
||||||
self.renderer.AddActor(actor)
|
self.renderer.AddActor(actor)
|
||||||
|
self.body_actors_orig.append(actor)
|
||||||
self.vtk_widget.GetRenderWindow().Render()
|
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):
|
def visualize_matrix(self, matrix):
|
||||||
points = vtk.vtkPoints()
|
points = vtk.vtkPoints()
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
@ -277,40 +311,6 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
|
|
||||||
return vtk_array
|
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:
|
def get_points_and_edges_from_polydata(self, polydata) -> list:
|
||||||
# Extract points
|
# Extract points
|
||||||
points = {}
|
points = {}
|
||||||
@ -353,7 +353,7 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
center_of_mass.SetInputData(projected_mesh)
|
center_of_mass.SetInputData(projected_mesh)
|
||||||
center_of_mass.SetUseScalarsAsWeights(False)
|
center_of_mass.SetUseScalarsAsWeights(False)
|
||||||
center_of_mass.Update()
|
center_of_mass.Update()
|
||||||
centroid = center_of_mass.GetCenter()
|
centroid = np.array(center_of_mass.GetCenter())
|
||||||
|
|
||||||
# Create a coordinate system on the plane
|
# Create a coordinate system on the plane
|
||||||
z_axis = np.array(normal)
|
z_axis = np.array(normal)
|
||||||
@ -363,68 +363,33 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
x_axis = x_axis / np.linalg.norm(x_axis)
|
x_axis = x_axis / np.linalg.norm(x_axis)
|
||||||
y_axis = np.cross(z_axis, x_axis)
|
y_axis = np.cross(z_axis, x_axis)
|
||||||
|
|
||||||
# Create transformation matrix
|
# Create rotation matrix (3x3)
|
||||||
matrix = vtk.vtkMatrix4x4()
|
rotation_matrix = np.column_stack((x_axis, y_axis, z_axis))
|
||||||
for i in range(3):
|
|
||||||
matrix.SetElement(i, 0, x_axis[i])
|
# Store the full transformation for later use if needed
|
||||||
matrix.SetElement(i, 1, y_axis[i])
|
full_transform = np.eye(4)
|
||||||
matrix.SetElement(i, 2, z_axis[i])
|
full_transform[:3, :3] = rotation_matrix
|
||||||
matrix.SetElement(i, 3, centroid[i])
|
full_transform[:3, 3] = centroid
|
||||||
self.local_matrix = matrix
|
self.local_matrix = full_transform
|
||||||
matrix.Invert()
|
|
||||||
|
|
||||||
# Transform points to 2D coordinates
|
# Transform points to 2D coordinates
|
||||||
transform = vtk.vtkTransform()
|
points = projected_mesh.GetPoints()
|
||||||
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()
|
|
||||||
|
|
||||||
xy_coordinates = []
|
xy_coordinates = []
|
||||||
|
|
||||||
for i in range(points.GetNumberOfPoints()):
|
for i in range(points.GetNumberOfPoints()):
|
||||||
point = points.GetPoint(i)
|
point = np.array(points.GetPoint(i))
|
||||||
xy_coordinates.append((-point[0], point[1]))
|
|
||||||
|
# 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
|
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)):
|
def add_normal_line(self, origin, normal, length=10.0, color=(1, 0, 0)):
|
||||||
# Normalize the normal vector
|
# Normalize the normal vector
|
||||||
normal = np.array(normal)
|
normal = np.array(normal)
|
||||||
@ -520,7 +485,7 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
edge_actor = vtk.vtkActor()
|
edge_actor = vtk.vtkActor()
|
||||||
edge_actor.SetMapper(edge_mapper)
|
edge_actor.SetMapper(edge_mapper)
|
||||||
edge_actor.GetProperty().SetColor(1.0, 0.0, 0.0) # Red color for picked edges
|
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
|
# Add the actor to the renderer and store it
|
||||||
self.renderer.AddActor(edge_actor)
|
self.renderer.AddActor(edge_actor)
|
||||||
@ -530,9 +495,18 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
self.compute_projection(False)
|
self.compute_projection(False)
|
||||||
|
|
||||||
elif len(self.selected_edges) > 2:
|
elif len(self.selected_edges) > 2:
|
||||||
|
del self.selected_edges[0]
|
||||||
pass
|
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
|
# Clear selection after projection was succesful
|
||||||
self.selected_edges = []
|
self.selected_edges = []
|
||||||
self.selected_normal = []
|
self.selected_normal = []
|
||||||
@ -559,21 +533,22 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
else:
|
else:
|
||||||
self.selected_normal = selected_normal
|
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
|
# Draw the normal line
|
||||||
normal_length = 50 # Adjust this value to change the length of 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))
|
color=(1, 0, 0))
|
||||||
|
|
||||||
polydata = self.picker.GetActor().GetMapper().GetInput()
|
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()
|
projected_points = projected_polydata.GetPoints()
|
||||||
#print("proj_points", projected_points)
|
#print("proj_points", projected_points)
|
||||||
|
|
||||||
# Extract 2D coordinates
|
# 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)
|
#print("3d_points_proj", self.project_tosketch_edge)
|
||||||
|
|
||||||
# Create a mapper and actor for the projected data
|
# Create a mapper and actor for the projected data
|
||||||
|
127
main.py
127
main.py
@ -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 uuid
|
||||||
import names
|
import names
|
||||||
from PySide6.QtCore import Qt, QPoint, Signal
|
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
|
# main, draw_widget, gl_widget
|
||||||
|
|
||||||
|
|
||||||
class ExtrudeDialog(QDialog):
|
class ExtrudeDialog(QDialog):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -30,6 +36,7 @@ class ExtrudeDialog(QDialog):
|
|||||||
|
|
||||||
# Symmetric checkbox
|
# Symmetric checkbox
|
||||||
self.symmetric_checkbox = QCheckBox('Symmetric Extrude')
|
self.symmetric_checkbox = QCheckBox('Symmetric Extrude')
|
||||||
|
self.invert_checkbox = QCheckBox('Invert Extrusion')
|
||||||
|
|
||||||
# OK and Cancel buttons
|
# OK and Cancel buttons
|
||||||
button_layout = QHBoxLayout()
|
button_layout = QHBoxLayout()
|
||||||
@ -43,12 +50,16 @@ class ExtrudeDialog(QDialog):
|
|||||||
# Add all widgets to main layout
|
# Add all widgets to main layout
|
||||||
layout.addLayout(length_layout)
|
layout.addLayout(length_layout)
|
||||||
layout.addWidget(self.symmetric_checkbox)
|
layout.addWidget(self.symmetric_checkbox)
|
||||||
|
|
||||||
|
layout.addLayout(length_layout)
|
||||||
|
layout.addWidget(self.invert_checkbox)
|
||||||
|
|
||||||
layout.addLayout(button_layout)
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
def get_values(self):
|
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):
|
class MainWindow(QMainWindow):
|
||||||
send_command = Signal(str)
|
send_command = Signal(str)
|
||||||
@ -129,7 +140,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.sketchWidget.create_proj_lines(edges)
|
self.sketchWidget.create_proj_lines(edges)
|
||||||
|
|
||||||
# CLear all selections after it has been projected
|
# 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.custom_3D_Widget.clear_actors_projection()
|
||||||
|
|
||||||
#self.sketchWidget.create_workplane_space(edges, normal)
|
#self.sketchWidget.create_workplane_space(edges, normal)
|
||||||
@ -189,13 +200,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.sketchWidget.mouse_mode = None
|
self.sketchWidget.mouse_mode = None
|
||||||
self.sketchWidget.reset_buffers()
|
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):
|
def draw_mesh(self):
|
||||||
name = self.ui.body_list.currentItem().text()
|
name = self.ui.body_list.currentItem().text()
|
||||||
print("selected_for disp", name)
|
print("selected_for disp", name)
|
||||||
@ -225,8 +229,10 @@ class MainWindow(QMainWindow):
|
|||||||
points_for_interact = []
|
points_for_interact = []
|
||||||
for point_to_poly in self.sketchWidget.slv_lines_main:
|
for point_to_poly in self.sketchWidget.slv_lines_main:
|
||||||
start, end = point_to_poly['ui_points']
|
start, end = point_to_poly['ui_points']
|
||||||
start_draw = self.translate_points_tup(start)
|
from_coord_start = self.sketchWidget.from_quadrant_coords_no_center(start)
|
||||||
end_draw = self.translate_points_tup(end)
|
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
|
line = start_draw, end_draw
|
||||||
points_for_interact.append(line)
|
points_for_interact.append(line)
|
||||||
|
|
||||||
@ -330,9 +336,44 @@ class MainWindow(QMainWindow):
|
|||||||
if isinstance(point, QPoint):
|
if isinstance(point, QPoint):
|
||||||
return point.x(), point.y()
|
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):
|
def send_extrude(self):
|
||||||
is_symmetric = None
|
is_symmetric = None
|
||||||
length = None
|
length = None
|
||||||
|
invert = None
|
||||||
selected = self.ui.sketch_list.currentItem()
|
selected = self.ui.sketch_list.currentItem()
|
||||||
name = selected.text()
|
name = selected.text()
|
||||||
points = self.model['sketch'][name]['sketch_points']
|
points = self.model['sketch'][name]['sketch_points']
|
||||||
@ -342,13 +383,10 @@ class MainWindow(QMainWindow):
|
|||||||
#detect loop that causes problems in mesh generation
|
#detect loop that causes problems in mesh generation
|
||||||
del points[-1]
|
del points[-1]
|
||||||
|
|
||||||
"""length, ok = QInputDialog.getDouble(self, 'Extrude Length', 'Enter a mm value:', decimals=2)
|
|
||||||
#TODO : Implement cancel"""
|
|
||||||
|
|
||||||
dialog = ExtrudeDialog(self)
|
dialog = ExtrudeDialog(self)
|
||||||
if dialog.exec():
|
if dialog.exec():
|
||||||
length, is_symmetric = dialog.get_values()
|
length, is_symmetric, invert = dialog.get_values()
|
||||||
print(f"Extrude length: {length}, Symmetric: {is_symmetric}")
|
print(f"Extrude length: {length}, Symmetric: {is_symmetric} Invert: {invert}")
|
||||||
else:
|
else:
|
||||||
length = 0
|
length = 0
|
||||||
print("Extrude cancelled")
|
print("Extrude cancelled")
|
||||||
@ -358,15 +396,31 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# Rotation is done in vtk matrix trans
|
# Rotation is done in vtk matrix trans
|
||||||
angle = 0
|
angle = 0
|
||||||
normal = [0, 0, 1]
|
|
||||||
f = geo.extrude_shape(points, length, angle, normal, is_symmetric)
|
|
||||||
|
|
||||||
if not is_symmetric:
|
normal = self.custom_3D_Widget.selected_normal
|
||||||
origin_z_lvl = length / 2
|
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:
|
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}"
|
name_op = f"extrd-{name}"
|
||||||
element = {
|
element = {
|
||||||
@ -388,7 +442,7 @@ class MainWindow(QMainWindow):
|
|||||||
points = self.model['operation'][name]['sdf_object']
|
points = self.model['operation'][name]['sdf_object']
|
||||||
self.list_selected.append(points)
|
self.list_selected.append(points)
|
||||||
|
|
||||||
if len(self.list_selected) > 1:
|
if len(self.list_selected) == 2:
|
||||||
geo = Geometry()
|
geo = Geometry()
|
||||||
f = geo.cut_shapes(self.list_selected[0], self.list_selected[1] )
|
f = geo.cut_shapes(self.list_selected[0], self.list_selected[1] )
|
||||||
|
|
||||||
@ -401,9 +455,12 @@ class MainWindow(QMainWindow):
|
|||||||
name_op = f"cut-{name}"
|
name_op = f"cut-{name}"
|
||||||
self.model['operation'][name_op] = element
|
self.model['operation'][name_op] = element
|
||||||
self.ui.body_list.addItem(name_op)
|
self.ui.body_list.addItem(name_op)
|
||||||
items = self.ui.sketch_list.findItems(name_op, Qt.MatchExactly)
|
items = self.ui.body_list.findItems(name_op, Qt.MatchExactly)
|
||||||
#self.ui.body_list.setCurrentItem(items[-1])
|
self.ui.body_list.setCurrentItem(items[-1])
|
||||||
|
self.custom_3D_Widget.clear_body_actors()
|
||||||
self.draw_mesh()
|
self.draw_mesh()
|
||||||
|
elif len(self.list_selected) > 2:
|
||||||
|
self.list_selected.clear()
|
||||||
else:
|
else:
|
||||||
print("mindestens 2!")
|
print("mindestens 2!")
|
||||||
|
|
||||||
@ -443,16 +500,22 @@ class Geometry:
|
|||||||
print("p2", p2)
|
print("p2", p2)
|
||||||
return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
|
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"""
|
"""2D to 3D sdf always first"""
|
||||||
f = polygon(points).rotate(angle)
|
f = polygon(points)
|
||||||
|
f = f.extrude(length)
|
||||||
|
|
||||||
if not symet:
|
# Calculate the offset vector (half the length in the direction of the normal)
|
||||||
print("Offsetting", symet)
|
offset = [n * (length / 2) for n in normal]
|
||||||
f = f.extrude(length).orient(normal).translate((0, 0, length/2)) # orient(normal)
|
|
||||||
|
|
||||||
else:
|
# Apply the offset in the direction of the normal
|
||||||
f = f.extrude(length).orient(normal)
|
f = f.translate(offset)
|
||||||
|
|
||||||
|
# Apply the centroid translation
|
||||||
|
#f = f.translate(centroid)
|
||||||
|
|
||||||
|
# Apply the orientation
|
||||||
|
f = f.orient(normal)
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
# Draw simple boundary based on the lines and depth
|
# Draw simple boundary based on the lines and depth
|
||||||
|
|
||||||
def generate_mesh(lines: list, z_origin: float, depth: float, symmetric: bool = True):
|
def generate_mesh(lines: list, z_origin: float, depth: float, invert :bool = False):
|
||||||
if symmetric:
|
|
||||||
depth1 = depth/2
|
origin = create_3D(lines, z_origin)
|
||||||
depth2 = -depth/2
|
if invert :
|
||||||
origin = create_3D(lines, z_origin, depth1)
|
extruded = create_3D(lines, z_origin - depth)
|
||||||
extruded = create_3D(lines, z_origin, depth2)
|
|
||||||
else:
|
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)
|
vert_lines = create_vert_lines(origin, extruded)
|
||||||
|
|
||||||
print(f"Result = {origin} / {extruded} / {vert_lines}")
|
print(f"Result = {origin} / {extruded} / {vert_lines}")
|
||||||
|
|
||||||
return origin + vert_lines + extruded
|
return origin + vert_lines + extruded
|
||||||
|
|
||||||
|
|
||||||
def create_vert_lines(origin, extruded):
|
def create_vert_lines(origin, extruded):
|
||||||
@ -26,16 +24,16 @@ def create_vert_lines(origin, extruded):
|
|||||||
return vert_lines
|
return vert_lines
|
||||||
|
|
||||||
|
|
||||||
def create_3D(lines, z_origin, depth):
|
def create_3D(lines, z_pos):
|
||||||
line_loop = []
|
line_loop = []
|
||||||
for coordinate2d in lines:
|
for coordinate2d in lines:
|
||||||
start, end = coordinate2d
|
start, end = coordinate2d
|
||||||
|
|
||||||
xs, ys = start
|
xs, ys = start
|
||||||
coordinate3d_start_orig = xs, -ys, z_origin + depth
|
coordinate3d_start_orig = xs, -ys, z_pos
|
||||||
|
|
||||||
xe, ye = end
|
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
|
line3d_orig = coordinate3d_start_orig, coordinate3d_end_orig
|
||||||
|
|
||||||
|
10
meshtest.py
10
meshtest.py
@ -1,7 +1,5 @@
|
|||||||
from sdf import *
|
from sdf import *
|
||||||
c = box(1).translate((0,0,0.2))
|
f = box(1).translate((1,1,-0.2))
|
||||||
f = capped_cylinder(-Z, Z, 0.5)
|
c = hexagon(1).extrude(1).orient([0,0,-1])
|
||||||
c.orient([0.5, 0.5, 1])
|
c = f & c
|
||||||
c = f - c
|
f.save("out.stl")
|
||||||
|
|
||||||
c.save("out.stl")
|
|
Loading…
x
Reference in New Issue
Block a user