- Fixed 2d sketch with transfrom
This commit is contained in:
		
							
								
								
									
										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
 | 
			
		||||
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):
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
									
									
									
									
								
							
							
						
						
									
										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 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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								meshtest.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								meshtest.py
									
									
									
									
									
								
							@@ -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")
 | 
			
		||||
		Reference in New Issue
	
	Block a user