- Basic polygon to body
This commit is contained in:
79
drawing_modules/draw_widget2d.py
Normal file
79
drawing_modules/draw_widget2d.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox
|
||||
from PySide6.QtGui import QPainter, QPen, QColor
|
||||
from PySide6.QtCore import Qt, QPoint
|
||||
|
||||
|
||||
class SnapLineWidget(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.points = []
|
||||
self.selected_line = None
|
||||
self.snapping_range = 20 # Range in pixels for snapping
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.LeftButton:
|
||||
self.points.append(event.pos())
|
||||
self.update()
|
||||
|
||||
if event.button() == Qt.RightButton:
|
||||
for i in range(len(self.points) - 1):
|
||||
if self.is_point_on_line(event.pos(), self.points[i], self.points[i + 1]):
|
||||
self.selected_line = i
|
||||
break
|
||||
else:
|
||||
self.selected_line = None
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if event.buttons() & Qt.LeftButton:
|
||||
if self.selected_line is not None:
|
||||
self.points[self.selected_line] = event.pos()
|
||||
else:
|
||||
self.points[-1] = event.pos()
|
||||
self.update()
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
pass
|
||||
|
||||
def distance(self, p1, p2):
|
||||
return ((p1.x() - p2.x()) ** 2 + (p1.y() - p2.y()) ** 2) ** 0.5
|
||||
|
||||
def is_point_on_line(self, p, p1, p2):
|
||||
distance1 = self.distance(p, p1)
|
||||
distance2 = self.distance(p, p2)
|
||||
total_distance = self.distance(p1, p2)
|
||||
return abs(distance1 + distance2 - total_distance) < 0.1
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QPainter(self)
|
||||
|
||||
# Set the background color
|
||||
painter.fillRect(self.rect(), QColor('white'))
|
||||
|
||||
pen = QPen(Qt.black)
|
||||
pen.setWidth(1)
|
||||
painter.setPen(pen)
|
||||
|
||||
for i in range(len(self.points) - 1):
|
||||
painter.drawLine(self.points[i], self.points[i + 1])
|
||||
|
||||
# Draw points
|
||||
for point in self.points:
|
||||
painter.drawEllipse(point, 3, 3)
|
||||
|
||||
if self.selected_line is not None:
|
||||
p1 = self.points[self.selected_line]
|
||||
p2 = self.points[self.selected_line + 1]
|
||||
painter.setPen(QPen(Qt.red, 2))
|
||||
painter.drawLine(p1, p2)
|
||||
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
window = SnapLineWidget()
|
||||
window.setWindowTitle("Snap Line Widget")
|
||||
window.resize(800, 600)
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
151
drawing_modules/gl_widget.py
Normal file
151
drawing_modules/gl_widget.py
Normal file
@@ -0,0 +1,151 @@
|
||||
import numpy as np
|
||||
from PySide6.QtOpenGLWidgets import QOpenGLWidget
|
||||
from PySide6.QtCore import Qt, QPoint
|
||||
from OpenGL.GL import *
|
||||
from OpenGL.GLU import *
|
||||
from stl import mesh
|
||||
|
||||
class OpenGLWidget(QOpenGLWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.stl_file = "out.stl" # Replace with your STL file path
|
||||
self.lastPos = QPoint()
|
||||
self.startPos = None
|
||||
self.endPos = None
|
||||
self.xRot = 0
|
||||
self.yRot = 0
|
||||
self.zoom = -10.0
|
||||
self.sketch = []
|
||||
self.gl_width = self.width() / 1000
|
||||
self.gl_height = self.height() / 1000
|
||||
|
||||
def map_value_to_range(self, value, value_min=0, value_max=1920, range_min=-1, range_max=1):
|
||||
value = max(value_min, min(value_max, value))
|
||||
mapped_value = ((value - value_min) / (value_max - value_min)) * (range_max - range_min) + range_min
|
||||
return mapped_value
|
||||
|
||||
def load_stl(self, filename):
|
||||
try:
|
||||
stl_mesh = mesh.Mesh.from_file(filename)
|
||||
|
||||
# Extract vertices
|
||||
vertices = np.concatenate([stl_mesh.v0, stl_mesh.v1, stl_mesh.v2])
|
||||
|
||||
# Calculate bounding box
|
||||
min_x, min_y, min_z = vertices.min(axis=0)
|
||||
max_x, max_y, max_z = vertices.max(axis=0)
|
||||
|
||||
# Calculate centroid
|
||||
centroid_x = (min_x + max_x) / 2.0
|
||||
centroid_y = (min_y + max_y) / 2.0
|
||||
centroid_z = (min_z + max_z) / 2.0
|
||||
|
||||
return stl_mesh.vectors, (centroid_x, centroid_y, centroid_z)
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File {filename} not found.")
|
||||
except Exception as e:
|
||||
print(f"Error loading {filename}: {e}")
|
||||
return None, (0, 0, 0)
|
||||
|
||||
def initializeGL(self):
|
||||
glClearColor(0, 0, 0, 1)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
def resizeGL(self, width, height):
|
||||
glViewport(0, 0, width, height)
|
||||
glMatrixMode(GL_PROJECTION)
|
||||
glLoadIdentity()
|
||||
aspect = width / float(height)
|
||||
|
||||
self.gl_width = self.width() / 1000
|
||||
self.gl_height = self.height() / 1000
|
||||
|
||||
gluPerspective(45.0, aspect, 1.0, 1000.0)
|
||||
glMatrixMode(GL_MODELVIEW)
|
||||
|
||||
def paintGL(self):
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
glLoadIdentity()
|
||||
|
||||
mesh_loaded, centroid = self.load_stl(self.stl_file)
|
||||
centroid_x, centroid_y, centroid_z = centroid
|
||||
|
||||
glTranslatef(0, 0, self.zoom)
|
||||
glRotatef(self.xRot, 1.0, 0.0, 0.0)
|
||||
glRotatef(self.yRot, 0.0, 1.0, 0.0)
|
||||
|
||||
glColor3f(1.0, 1.0, 1.0)
|
||||
|
||||
self.draw_area()
|
||||
|
||||
if mesh is not None:
|
||||
# Scale the object
|
||||
scale_factor = 0.001 # Example scale factor (adjust as needed)
|
||||
glScalef(scale_factor, scale_factor, scale_factor)
|
||||
|
||||
# Translate to move the centroid of the object to the origin
|
||||
glTranslatef(-centroid_x, -centroid_y, -centroid_z)
|
||||
|
||||
|
||||
|
||||
self.draw_stl(mesh_loaded)
|
||||
|
||||
def draw_stl(self, vertices):
|
||||
glEnable(GL_LIGHTING)
|
||||
glEnable(GL_LIGHT0)
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
glEnable(GL_COLOR_MATERIAL)
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, (0, 1, 1, 0))
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, (0.6, 0.6, 0.6, 1.0))
|
||||
|
||||
glBegin(GL_TRIANGLES)
|
||||
for triangle in vertices:
|
||||
for vertex in triangle:
|
||||
glVertex3fv(vertex)
|
||||
glEnd()
|
||||
|
||||
"""# Draw outer vertices as points
|
||||
glDisable(GL_LIGHTING)
|
||||
glColor3f(1.0, 0.0, 0.0) # Set color to red
|
||||
glPointSize(5.0) # Set point size
|
||||
glBegin(GL_POINTS)
|
||||
for vertex in vertices:
|
||||
glVertex3fv(vertex)
|
||||
glEnd()"""
|
||||
|
||||
def draw_area(self):
|
||||
glColor3f(0.5, 0.5, 0.5) # Gray color
|
||||
|
||||
glBegin(GL_LINES)
|
||||
for x in range(0, self.width(), 20):
|
||||
x_ndc = self.map_value_to_range(x, 0, value_max=self.width(), range_min=-self.gl_width, range_max=self.gl_width)
|
||||
glVertex2f(x_ndc, -self.gl_height) # Start from y = -1
|
||||
glVertex2f(x_ndc, self.gl_height) # End at y = 1
|
||||
|
||||
for y in range(0, self.height(), 20):
|
||||
y_ndc = self.map_value_to_range(y, 0, value_max=self.height(), range_min=-self.gl_height, range_max=self.gl_height)
|
||||
glVertex2f(-self.gl_width, y_ndc) # Start from x = -1
|
||||
glVertex2f(self.gl_width, y_ndc) # End at x = 1
|
||||
glEnd()
|
||||
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
dx = event.x() - self.lastPos.x()
|
||||
dy = event.y() - self.lastPos.y()
|
||||
|
||||
if event.buttons() & Qt.MouseButton.LeftButton :
|
||||
self.xRot += 0.5 * dy
|
||||
self.yRot += 0.5 * dx
|
||||
self.lastPos = event.pos()
|
||||
self.update()
|
||||
|
||||
def wheelEvent(self, event):
|
||||
delta = event.angleDelta().y()
|
||||
self.zoom += delta / 120
|
||||
self.update()
|
||||
|
||||
def aspect_ratio(self):
|
||||
return self.width() / self.height() * (1.0 / abs(self.zoom))
|
||||
|
||||
Reference in New Issue
Block a user