- Started Solvespace implementation solver
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
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
|
||||
@@ -6,61 +9,154 @@ 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.line_mode = False
|
||||
self.setMouseTracking(True)
|
||||
self.mouse_mode = False
|
||||
self.wp = None
|
||||
self.solv = SolverSystem()
|
||||
|
||||
def solve_constraint(self):
|
||||
solv = SolverSystem()
|
||||
wp = solv.create_2d_base() # Workplane (Entity)
|
||||
p0 = solv.add_point_2d(0, 0, wp) # Entity
|
||||
solv.dragged(p0, wp) # Make a constraint with the entity
|
||||
...
|
||||
line0 = solv.add_line_2d(p0, p1, wp) # Create entity with others
|
||||
...
|
||||
line1 = solv.add_line_2d(p0, p3, wp)
|
||||
solv.angle(line0, line1, 45, wp) # Constrain two entities
|
||||
line1 = solv.entity(-1) # Entity handle can be re-generated and negatively indexed
|
||||
...
|
||||
if solv.solve() == ResultFlag.OKAY:
|
||||
# Get the result (unpack from the entity or parameters)
|
||||
# x and y are actually float type
|
||||
dof = solv.dof()
|
||||
x, y = solv.params(p2.params)
|
||||
...
|
||||
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:
|
||||
# Error!
|
||||
# Get the list of all constraints
|
||||
failures = solv.failures()
|
||||
...
|
||||
print("Handle number not found.")
|
||||
|
||||
return 0
|
||||
|
||||
def set_points(self, points: list):
|
||||
self.points = points
|
||||
#self.update()
|
||||
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):
|
||||
if event.button() == Qt.LeftButton and self.line_mode:
|
||||
self.points.append(event.pos())
|
||||
self.update()
|
||||
relation = {
|
||||
'handle_nr': None,
|
||||
'solv_handle': None
|
||||
}
|
||||
|
||||
elif 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
|
||||
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):
|
||||
if event.buttons() & Qt.RightButton:
|
||||
if self.selected_line is not None:
|
||||
self.points[self.selected_line] = event.pos()
|
||||
else:
|
||||
self.points[-1] = event.pos()
|
||||
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):
|
||||
@@ -69,6 +165,10 @@ class SketchWidget(QWidget):
|
||||
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)
|
||||
@@ -93,11 +193,18 @@ class SketchWidget(QWidget):
|
||||
for point in self.points:
|
||||
painter.drawEllipse(point, 3, 3)
|
||||
|
||||
if self.selected_line is not None:
|
||||
#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.drawLine(p1, p2)"""
|
||||
painter.end()
|
||||
|
||||
def clear_sketch(self):
|
||||
|
||||
25
drawing_modules/solvespace_example.py
Normal file
25
drawing_modules/solvespace_example.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from python_solvespace import SolverSystem, ResultFlag
|
||||
|
||||
def solve_constraint(self):
|
||||
solv = SolverSystem()
|
||||
wp = solv.create_2d_base() # Workplane (Entity)
|
||||
p0 = solv.add_point_2d(0, 0, wp) # Entity
|
||||
solv.dragged(p0, wp) # Make a constraint with the entity
|
||||
...
|
||||
line0 = solv.add_line_2d(p0, p1, wp) # Create entity with others
|
||||
...
|
||||
line1 = solv.add_line_2d(p0, p3, wp)
|
||||
solv.angle(line0, line1, 45, wp) # Constrain two entities
|
||||
line1 = solv.entity(-1) # Entity handle can be re-generated and negatively indexed
|
||||
...
|
||||
if solv.solve() == ResultFlag.OKAY:
|
||||
# Get the result (unpack from the entity or parameters)
|
||||
# x and y are actually float type
|
||||
dof = solv.dof()
|
||||
x, y = solv.params(p2.params)
|
||||
...
|
||||
else:
|
||||
# Error!
|
||||
# Get the list of all constraints
|
||||
failures = solv.failures()
|
||||
...
|
||||
Reference in New Issue
Block a user