diff --git a/drawing_modules/draw_widget2d.py b/drawing_modules/draw_widget2d.py index 5e48ef3..25b5e8a 100644 --- a/drawing_modules/draw_widget2d.py +++ b/drawing_modules/draw_widget2d.py @@ -356,8 +356,11 @@ class SketchWidget(QWidget): print("Buffer state", self.line_draw_buffer) if self.line_draw_buffer[0] and self.line_draw_buffer[1]: + point_slv1 = self.get_handle_from_ui_point(self.line_draw_buffer[0]) point_slv2 = self.get_handle_from_ui_point(self.line_draw_buffer[1]) + print(point_slv1) + print(point_slv2) line = self.solv.add_line_2d(point_slv1, point_slv2, self.sketch.working_plane) @@ -768,7 +771,139 @@ class SketchWidget(QWidget): return self.width() / self.height() * (1.0 / abs(self.zoom)) -# Example usage +class Point2D: + """Improved oop aaproach?""" + def __init__(self): + self.ui_point = None + self.solve_handle_nr = None + self.solve_handle = None + self.part_of_entity = None + + def to_quadrant_coords(self, point): + """Translate linear coordinates to quadrant coordinates.""" + center_x = self.width() // 2 + center_y = self.height() // 2 + quadrant_x = point.x() - center_x + 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): + """Invert Y Coordinate for mesh""" + center_x = 0 + center_y = 0 + widget_x = point.x() + widget_y = -point.y() + + return QPoint(int(widget_x), int(widget_y)) + + 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 get_handle_from_ui_point(self, ui_point: QPoint): + """Input QPoint and you shall reveive a slvs entity handle!""" + for point in self.sketch.slv_points: + if ui_point == point['ui_point']: + slv_handle = point['solv_handle'] + + return slv_handle + + def get_line_handle_from_ui_point(self, ui_point: QPoint): + """Input Qpoint that is on a line and you shall receive the handle of the line!""" + for target_line_con in self.sketch.slv_lines: + if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]): + slv_handle = target_line_con['solv_handle'] + + return slv_handle + + def get_point_line_handles_from_ui_point(self, ui_point: QPoint) -> tuple: + """Input Qpoint that is on a line and you shall receive the handles of the points of the line!""" + for target_line_con in self.sketch.slv_lines: + if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]): + lines_to_cons = target_line_con['solv_entity_points'] + + return lines_to_cons + + def distance(self, p1, p2): + return math.sqrt((p1.x() - p2.x())**2 + (p1.y() - p2.y())**2) + + def calculate_midpoint(self, point1, point2): + mx = (point1.x() + point2.x()) // 2 + my = (point1.y() + point2.y()) // 2 + return QPoint(mx, my) + + def is_point_on_line(self, p, p1, p2, tolerance=5): + # Calculate the lengths of the sides of the triangle + a = self.distance(p, p1) + b = self.distance(p, p2) + c = self.distance(p1, p2) + + # Calculate the semi-perimeter + s = (a + b + c) / 2 + + # Calculate the area using Heron's formula + area = math.sqrt(s * (s - a) * (s - b) * (s - c)) + + # Calculate the height (perpendicular distance from the point to the line) + if c > 0: + height = (2 * area) / c + # Check if the height is within the tolerance distance to the line + if height > tolerance: + return False + + # Check if the projection of the point onto the line is within the line segment + dot_product = ((p.x() - p1.x()) * (p2.x() - p1.x()) + (p.y() - p1.y()) * (p2.y() - p1.y())) / (c ** 2) + + return 0 <= dot_product <= 1 + else: + return None + + def viewport_to_local_coord(self, qt_pos : QPoint) -> QPoint: + return QPoint(self.to_quadrant_coords(qt_pos)) + + +class Line2D: + pass + + + if __name__ == "__main__": import sys diff --git a/drawing_modules/solvespace_example.py b/drawing_modules/solvespace_example.py index e1aeb28..e405f59 100644 --- a/drawing_modules/solvespace_example.py +++ b/drawing_modules/solvespace_example.py @@ -1,25 +1,35 @@ from python_solvespace import SolverSystem, ResultFlag -def solve_constraint(self): +def solve_constraint(): solv = SolverSystem() wp = solv.create_2d_base() # Workplane (Entity) p0 = solv.add_point_2d(0, 0, wp) # Entity + p1 = solv.add_point_2d(10, 10, wp) # Entity + p2 = solv.add_point_2d(0, 10, 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.add_line_2d(p0, p2, wp) + #solv.angle(line0, line1, 45, wp) # Constrain two entities + solv.coincident(p0, p1, wp) + solv.add_constraint(100006, wp, 0, p1,p2, line0, line1) + line1 = solv.entity(-1) # Entity handle can be re-generated and negatively indexed - ... + solv. 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) - ... + x, y = solv.params(p1.params) + print(dof) + print(x) + print(y) + else: # Error! # Get the list of all constraints failures = solv.failures() - ... \ No newline at end of file + print(failures) + ... + +solve_constraint() \ No newline at end of file diff --git a/main.py b/main.py index 935998f..405349a 100644 --- a/main.py +++ b/main.py @@ -267,6 +267,7 @@ class MainWindow(QMainWindow): sketch.slv_lines = [] sketch.proj_points = [] sketch.proj_lines = [] + self.sketchWidget.reset_buffers() self.sketchWidget.set_sketch(sketch) def add_new_sketch_wp(self): @@ -279,6 +280,7 @@ class MainWindow(QMainWindow): sketch.slv_lines = [] sketch.proj_points = self.custom_3D_Widget.project_tosketch_points sketch.proj_lines = self.custom_3D_Widget.project_tosketch_lines + self.sketchWidget.reset_buffers() self.sketchWidget.set_sketch(sketch) self.sketchWidget.create_workplane_projected() self.sketchWidget.convert_proj_points() @@ -765,7 +767,6 @@ class Project: assembly: Assembly = None - if __name__ == "__main__": app = QApplication([]) window = MainWindow() diff --git a/modules/out.stl b/modules/out.stl deleted file mode 100644 index 811aa0d..0000000 Binary files a/modules/out.stl and /dev/null differ diff --git a/requirements.txt b/requirements.txt index ff39233..a8f207e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,9 +2,13 @@ matplotlib==3.8.2 numpy==1.26.2 Pillow==10.1.0 Pint==0.22 -pygame==2.5.2 PySide6==6.6.1 rich==13.7.0 scikit-image==0.22.0 scipy==1.11.4 vtk==9.3.0 + +names~=0.3.0 +shapely~=2.0.4 +pyvista~=0.43.10 +pyvistaqt~=0.11.1 \ No newline at end of file