fluencyCAD/drawing_modules/draw_widget2d.py
2024-06-19 17:14:58 +02:00

225 lines
6.6 KiB
Python

import re
from copy import copy
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox
from PySide6.QtGui import QPainter, QPen, QColor
from PySide6.QtCore import Qt, QPoint
from python_solvespace import SolverSystem, ResultFlag
class SketchWidget(QWidget):
def __init__(self):
super().__init__()
self.hovered_point = None
self.line_buffer = None
self.pt_pt_buffer = None
self.points = []
self.selected_line = None
self.snapping_range = 20 # Range in pixels for snapping
self.setMouseTracking(True)
self.mouse_mode = False
self.wp = None
self.solv = SolverSystem()
self.solventies = {}
def create_worplane(self):
self.wp = self.solv.create_2d_base()
def get_handle_nr(self, input_str: str) -> int:
# Define the regex pattern to extract the handle number
pattern = r"handle=(\d+)"
# Use re.search to find the handle number in the string
match = re.search(pattern, input_str)
if match:
handle_number = int(match.group(1))
print(f"Handle number: {handle_number}")
return int(handle_number)
else:
print("Handle number not found.")
return 0
def get_keys(self, d: dict, target: QPoint) -> list:
result = []
path = []
print(d)
print(target)
for k, v in d.items():
path.append(k)
if isinstance(v, dict):
self.get_keys(v, target)
if v == target:
result.append(copy(path))
path.pop()
return result
def mousePressEvent(self, event):
relation = {
'handle_nr': None,
'solv_handle': None
}
if event.button() == Qt.LeftButton and self.mouse_mode == "line":
clicked_pos = event.pos()
# Paintline
"""self.points.append(clicked_pos)
self.update()"""
u = clicked_pos.x()
v = clicked_pos.y()
point = self.solv.add_point_2d(u, v, self.wp)
#print(point)
self.solv.dragged(point, self.wp)
# Solverline
if self.line_buffer:
line = self.solv.add_line_2d(self.line_buffer, point, self.wp)
#print(line)
self.line_buffer = point
# Track Relationship
handle_nr = self.get_handle_nr(str(point))
relation['handle_nr'] = handle_nr
relation['solv_handle'] = point
self.solventies[clicked_pos] = relation
self.points = list(self.solventies)
#print(self.points)
if event.button() == Qt.LeftButton and self.mouse_mode == "pt_pt":
point_solve_now = self.solventies[self.hovered_point]['solv_handle']
if self.pt_pt_buffer:
point_solve_old = self.solventies[self.pt_pt_buffer]['solv_handle']
print(point_solve_old)
print(point_solve_now)
self.solv.coincident(point_solve_now, point_solve_old, self.wp)
if self.solv.solve() == ResultFlag.OKAY:
# Get the result (unpack from the entity or parameters)
# x and y are actually float type
dof = self.solv.dof()
print(dof)
if self.pt_pt_buffer:
# Get the entry form the old point and copy it into new point with the new key and postion (key = postiion
move_point = self.solventies[self.pt_pt_buffer]
print(move_point)
del self.solventies[self.pt_pt_buffer]
self.solventies[self.hovered_point] = move_point
#print(f"Coordinates: {x1}, {y1}; {x2}, {y2}")
elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE:
print("Solve_failed - Converge" )
elif self.solv.solve() == ResultFlag.TOO_MANY_UNKNOWNS:
print("Solve_failed - Unknowns" )
elif self.solv.solve() == ResultFlag.INCONSISTENT:
print("Solve_failed - Incons" )
self.points = []
self.points = list(self.solventies)
print(self.points)
self.pt_pt_buffer = self.hovered_point
def mouseMoveEvent(self, event):
closest_point = None
min_distance = float('inf')
threshold = 10 # Distance threshold for highlighting
for point in self.points:
distance = (event.pos() - point).manhattanLength()
if distance < threshold and distance < min_distance:
closest_point = point
min_distance = distance
if closest_point != self.hovered_point:
self.hovered_point = closest_point
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 set_points(self, points: list):
self.points = points
#self.update()
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) < 1
def paintEvent(self, event):
painter = QPainter(self)
# Set the background color
painter.fillRect(self.rect(), QColor('black'))
pen = QPen(Qt.gray)
pen.setWidth(2)
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)
#Highlight point hovered
if self.hovered_point:
highlight_pen = QPen(QColor(255, 0, 0))
highlight_pen.setWidth(2)
painter.setPen(highlight_pen)
painter.drawEllipse(self.hovered_point, 5, 5)
"""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)"""
painter.end()
def clear_sketch(self):
self.points = []
self.update()
# Example usage
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = SketchWidget()
window.setWindowTitle("Snap Line Widget")
window.resize(800, 600)
window.show()
sys.exit(app.exec())