Merge pull request 'structure' (#7) from structure into master
Reviewed-on: BKLronin/fluency#7
This commit is contained in:
commit
0a9d557ce0
31
Gui.py
31
Gui.py
@ -419,6 +419,7 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pb_con_perp = QPushButton(self.groupBox_3)
|
self.pb_con_perp = QPushButton(self.groupBox_3)
|
||||||
self.pb_con_perp.setObjectName(u"pb_con_perp")
|
self.pb_con_perp.setObjectName(u"pb_con_perp")
|
||||||
self.pb_con_perp.setCheckable(True)
|
self.pb_con_perp.setCheckable(True)
|
||||||
|
self.pb_con_perp.setAutoExclusive(False)
|
||||||
|
|
||||||
self.gridLayout_4.addWidget(self.pb_con_perp, 1, 1, 1, 1)
|
self.gridLayout_4.addWidget(self.pb_con_perp, 1, 1, 1, 1)
|
||||||
|
|
||||||
@ -454,6 +455,7 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pb_con_mid = QPushButton(self.groupBox_3)
|
self.pb_con_mid = QPushButton(self.groupBox_3)
|
||||||
self.pb_con_mid.setObjectName(u"pb_con_mid")
|
self.pb_con_mid.setObjectName(u"pb_con_mid")
|
||||||
self.pb_con_mid.setCheckable(True)
|
self.pb_con_mid.setCheckable(True)
|
||||||
|
self.pb_con_mid.setAutoExclusive(False)
|
||||||
|
|
||||||
self.gridLayout_4.addWidget(self.pb_con_mid, 1, 0, 1, 1)
|
self.gridLayout_4.addWidget(self.pb_con_mid, 1, 0, 1, 1)
|
||||||
|
|
||||||
@ -469,11 +471,11 @@ class Ui_fluencyCAD(object):
|
|||||||
self.tabWidget.setSizePolicy(sizePolicy5)
|
self.tabWidget.setSizePolicy(sizePolicy5)
|
||||||
self.tabWidget.setMaximumSize(QSize(200, 16777215))
|
self.tabWidget.setMaximumSize(QSize(200, 16777215))
|
||||||
self.tabWidget.setTabPosition(QTabWidget.South)
|
self.tabWidget.setTabPosition(QTabWidget.South)
|
||||||
self.widget = QWidget()
|
self.snaps = QWidget()
|
||||||
self.widget.setObjectName(u"widget")
|
self.snaps.setObjectName(u"snaps")
|
||||||
self.verticalLayout_3 = QVBoxLayout(self.widget)
|
self.verticalLayout_3 = QVBoxLayout(self.snaps)
|
||||||
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
|
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
|
||||||
self.groupBox_5 = QGroupBox(self.widget)
|
self.groupBox_5 = QGroupBox(self.snaps)
|
||||||
self.groupBox_5.setObjectName(u"groupBox_5")
|
self.groupBox_5.setObjectName(u"groupBox_5")
|
||||||
sizePolicy6 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
|
sizePolicy6 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
|
||||||
sizePolicy6.setHorizontalStretch(0)
|
sizePolicy6.setHorizontalStretch(0)
|
||||||
@ -491,6 +493,7 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pb_snap_vert = QPushButton(self.groupBox_5)
|
self.pb_snap_vert = QPushButton(self.groupBox_5)
|
||||||
self.pb_snap_vert.setObjectName(u"pb_snap_vert")
|
self.pb_snap_vert.setObjectName(u"pb_snap_vert")
|
||||||
self.pb_snap_vert.setCheckable(True)
|
self.pb_snap_vert.setCheckable(True)
|
||||||
|
self.pb_snap_vert.setAutoExclusive(False)
|
||||||
|
|
||||||
self.gridLayout_11.addWidget(self.pb_snap_vert, 2, 1, 1, 1)
|
self.gridLayout_11.addWidget(self.pb_snap_vert, 2, 1, 1, 1)
|
||||||
|
|
||||||
@ -516,12 +519,14 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pushButton_7 = QPushButton(self.groupBox_5)
|
self.pushButton_7 = QPushButton(self.groupBox_5)
|
||||||
self.pushButton_7.setObjectName(u"pushButton_7")
|
self.pushButton_7.setObjectName(u"pushButton_7")
|
||||||
self.pushButton_7.setCheckable(True)
|
self.pushButton_7.setCheckable(True)
|
||||||
|
self.pushButton_7.setAutoExclusive(False)
|
||||||
|
|
||||||
self.gridLayout_11.addWidget(self.pushButton_7, 3, 0, 1, 1)
|
self.gridLayout_11.addWidget(self.pushButton_7, 3, 0, 1, 1)
|
||||||
|
|
||||||
self.pb_snap_horiz = QPushButton(self.groupBox_5)
|
self.pb_snap_horiz = QPushButton(self.groupBox_5)
|
||||||
self.pb_snap_horiz.setObjectName(u"pb_snap_horiz")
|
self.pb_snap_horiz.setObjectName(u"pb_snap_horiz")
|
||||||
self.pb_snap_horiz.setCheckable(True)
|
self.pb_snap_horiz.setCheckable(True)
|
||||||
|
self.pb_snap_horiz.setAutoExclusive(False)
|
||||||
|
|
||||||
self.gridLayout_11.addWidget(self.pb_snap_horiz, 2, 0, 1, 1)
|
self.gridLayout_11.addWidget(self.pb_snap_horiz, 2, 0, 1, 1)
|
||||||
|
|
||||||
@ -534,28 +539,32 @@ class Ui_fluencyCAD(object):
|
|||||||
|
|
||||||
self.pushButton_8 = QPushButton(self.groupBox_5)
|
self.pushButton_8 = QPushButton(self.groupBox_5)
|
||||||
self.pushButton_8.setObjectName(u"pushButton_8")
|
self.pushButton_8.setObjectName(u"pushButton_8")
|
||||||
|
self.pushButton_8.setCheckable(True)
|
||||||
|
self.pushButton_8.setAutoExclusive(False)
|
||||||
|
|
||||||
self.gridLayout_11.addWidget(self.pushButton_8, 0, 0, 1, 1)
|
self.gridLayout_11.addWidget(self.pushButton_8, 0, 0, 1, 1)
|
||||||
|
|
||||||
self.pb_snap_midp = QPushButton(self.groupBox_5)
|
self.pb_snap_midp = QPushButton(self.groupBox_5)
|
||||||
self.pb_snap_midp.setObjectName(u"pb_snap_midp")
|
self.pb_snap_midp.setObjectName(u"pb_snap_midp")
|
||||||
self.pb_snap_midp.setCheckable(True)
|
self.pb_snap_midp.setCheckable(True)
|
||||||
|
self.pb_snap_midp.setAutoExclusive(False)
|
||||||
|
|
||||||
self.gridLayout_11.addWidget(self.pb_snap_midp, 0, 1, 1, 1)
|
self.gridLayout_11.addWidget(self.pb_snap_midp, 0, 1, 1, 1)
|
||||||
|
|
||||||
self.pb_snap_angle = QPushButton(self.groupBox_5)
|
self.pb_snap_angle = QPushButton(self.groupBox_5)
|
||||||
self.pb_snap_angle.setObjectName(u"pb_snap_angle")
|
self.pb_snap_angle.setObjectName(u"pb_snap_angle")
|
||||||
self.pb_snap_angle.setCheckable(True)
|
self.pb_snap_angle.setCheckable(True)
|
||||||
|
self.pb_snap_angle.setAutoExclusive(False)
|
||||||
|
|
||||||
self.gridLayout_11.addWidget(self.pb_snap_angle, 3, 1, 1, 1)
|
self.gridLayout_11.addWidget(self.pb_snap_angle, 3, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
self.verticalLayout_3.addWidget(self.groupBox_5)
|
self.verticalLayout_3.addWidget(self.groupBox_5)
|
||||||
|
|
||||||
self.tabWidget.addTab(self.widget, "")
|
self.tabWidget.addTab(self.snaps, "")
|
||||||
self.widget1 = QWidget()
|
self.settings = QWidget()
|
||||||
self.widget1.setObjectName(u"widget1")
|
self.settings.setObjectName(u"settings")
|
||||||
self.tabWidget.addTab(self.widget1, "")
|
self.tabWidget.addTab(self.settings, "")
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.tabWidget, 3, 0, 1, 1)
|
self.gridLayout.addWidget(self.tabWidget, 3, 0, 1, 1)
|
||||||
|
|
||||||
@ -582,7 +591,7 @@ class Ui_fluencyCAD(object):
|
|||||||
self.retranslateUi(fluencyCAD)
|
self.retranslateUi(fluencyCAD)
|
||||||
|
|
||||||
self.InputTab.setCurrentIndex(0)
|
self.InputTab.setCurrentIndex(0)
|
||||||
self.tabWidget.setCurrentIndex(1)
|
self.tabWidget.setCurrentIndex(0)
|
||||||
|
|
||||||
|
|
||||||
QMetaObject.connectSlotsByName(fluencyCAD)
|
QMetaObject.connectSlotsByName(fluencyCAD)
|
||||||
@ -710,8 +719,8 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pushButton_8.setText(QCoreApplication.translate("fluencyCAD", u"Pnt", None))
|
self.pushButton_8.setText(QCoreApplication.translate("fluencyCAD", u"Pnt", None))
|
||||||
self.pb_snap_midp.setText(QCoreApplication.translate("fluencyCAD", u"MidP", None))
|
self.pb_snap_midp.setText(QCoreApplication.translate("fluencyCAD", u"MidP", None))
|
||||||
self.pb_snap_angle.setText(QCoreApplication.translate("fluencyCAD", u"Angles", None))
|
self.pb_snap_angle.setText(QCoreApplication.translate("fluencyCAD", u"Angles", None))
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.widget), QCoreApplication.translate("fluencyCAD", u"Setg 1", None))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.snaps), QCoreApplication.translate("fluencyCAD", u"Setg 1", None))
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.widget1), QCoreApplication.translate("fluencyCAD", u"Setg 2", None))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.settings), QCoreApplication.translate("fluencyCAD", u"Setg 2", None))
|
||||||
self.menuFile.setTitle(QCoreApplication.translate("fluencyCAD", u"File", None))
|
self.menuFile.setTitle(QCoreApplication.translate("fluencyCAD", u"File", None))
|
||||||
self.menuSettings.setTitle(QCoreApplication.translate("fluencyCAD", u"Settings", None))
|
self.menuSettings.setTitle(QCoreApplication.translate("fluencyCAD", u"Settings", None))
|
||||||
# retranslateUi
|
# retranslateUi
|
||||||
|
@ -32,4 +32,4 @@ So far these are the elements:
|
|||||||
- Code: A special type that directly builds bodys from sdfCAD code.
|
- Code: A special type that directly builds bodys from sdfCAD code.
|
||||||
- Body: The 3D meshed result from sdfCAD
|
- Body: The 3D meshed result from sdfCAD
|
||||||
- Sketch: The base to draw new entities.
|
- Sketch: The base to draw new entities.
|
||||||
- Interactor: A special component mesh that is used to manipulate the bodys in 3d view.
|
- Interactor (edges): A special component mesh that is used to manipulate the bodys in 3d view.
|
@ -24,15 +24,60 @@ class SketchWidget(QWidget):
|
|||||||
self.hovered_point = None
|
self.hovered_point = None
|
||||||
self.selected_line = None
|
self.selected_line = None
|
||||||
|
|
||||||
|
### Display Settings
|
||||||
self.snapping_range = 20 # Range in pixels for snapping
|
self.snapping_range = 20 # Range in pixels for snapping
|
||||||
self.zoom = 1
|
self.zoom = 1
|
||||||
|
|
||||||
|
# Mouse Input
|
||||||
self.setMouseTracking(True)
|
self.setMouseTracking(True)
|
||||||
self.mouse_mode = False
|
self.mouse_mode = False
|
||||||
|
self.is_construct = False
|
||||||
|
|
||||||
|
self.snap_mode = {
|
||||||
|
"point": False,
|
||||||
|
"mpoint": False,
|
||||||
|
"horiz": False,
|
||||||
|
"vert":False,
|
||||||
|
"grid": False,
|
||||||
|
"angle": False
|
||||||
|
}
|
||||||
|
|
||||||
|
# Solver
|
||||||
self.solv = SolverSystem()
|
self.solv = SolverSystem()
|
||||||
|
|
||||||
self.sketch = Sketch2d()
|
self.sketch = Sketch2d()
|
||||||
|
|
||||||
|
def act_line_mode(self, checked):
|
||||||
|
if checked:
|
||||||
|
self.mouse_mode = 'line'
|
||||||
|
print(self.mouse_mode)
|
||||||
|
else:
|
||||||
|
self.mouse_mode = None
|
||||||
|
|
||||||
|
def act_constrain_pt_pt_mode(self):
|
||||||
|
self.mouse_mode = 'pt_pt'
|
||||||
|
|
||||||
|
def act_constrain_pt_line_mode(self):
|
||||||
|
self.mouse_mode = 'pt_line'
|
||||||
|
|
||||||
|
def act_constrain_horiz_line_mode(self):
|
||||||
|
self.mouse_mode = 'horiz'
|
||||||
|
|
||||||
|
def act_constrain_vert_line_mode(self):
|
||||||
|
self.mouse_mode = 'vert'
|
||||||
|
|
||||||
|
def act_constrain_distance_mode(self):
|
||||||
|
self.mouse_mode = 'distance'
|
||||||
|
|
||||||
|
def act_constrain_mid_point_mode(self):
|
||||||
|
self.mouse_mode = 'pb_con_mid'
|
||||||
|
|
||||||
|
def on_snap_mode_change(self, helper_type: str, value: bool):
|
||||||
|
self.snap_mode[helper_type] = value
|
||||||
|
|
||||||
|
def on_construct_change(self, checked):
|
||||||
|
self.is_construct = checked
|
||||||
|
|
||||||
def create_sketch(self, sketch_in ):
|
def create_sketch(self, sketch_in ):
|
||||||
self.sketch = Sketch2d()
|
self.sketch = Sketch2d()
|
||||||
self.sketch.id = sketch_in.id
|
self.sketch.id = sketch_in.id
|
||||||
@ -46,6 +91,7 @@ class SketchWidget(QWidget):
|
|||||||
return self.sketch
|
return self.sketch
|
||||||
|
|
||||||
def reset_buffers(self):
|
def reset_buffers(self):
|
||||||
|
self.mouse_mode = None
|
||||||
self.line_draw_buffer = [None, None]
|
self.line_draw_buffer = [None, None]
|
||||||
self.drag_buffer = [None, None]
|
self.drag_buffer = [None, None]
|
||||||
self.main_buffer = [None, None]
|
self.main_buffer = [None, None]
|
||||||
@ -235,11 +281,12 @@ class SketchWidget(QWidget):
|
|||||||
Go through solversystem and check points2d for changes in position after solving
|
Go through solversystem and check points2d for changes in position after solving
|
||||||
:return: List with points that now have a different position
|
:return: List with points that now have a different position
|
||||||
"""
|
"""
|
||||||
|
|
||||||
old_points_ui = []
|
old_points_ui = []
|
||||||
new_points_ui = []
|
new_points_ui = []
|
||||||
|
|
||||||
for old_point_ui in self.sketch.points:
|
for index, old_point_ui in enumerate(self.sketch.points):
|
||||||
old_points_ui.append(old_point_ui.ui_point)
|
old_points_ui.append((index, old_point_ui.ui_point))
|
||||||
|
|
||||||
for i in range(self.sketch.entity_len()):
|
for i in range(self.sketch.entity_len()):
|
||||||
# Iterate though full length because mixed list from SS
|
# Iterate though full length because mixed list from SS
|
||||||
@ -255,9 +302,10 @@ class SketchWidget(QWidget):
|
|||||||
if len(old_points_ui) != len(new_points_ui):
|
if len(old_points_ui) != len(new_points_ui):
|
||||||
print(f"Length mismatch {len(old_points_ui)} - {len(new_points_ui)}")
|
print(f"Length mismatch {len(old_points_ui)} - {len(new_points_ui)}")
|
||||||
|
|
||||||
for index, (old_point, new_point) in enumerate(zip(old_points_ui, new_points_ui)):
|
for (old_index, old_point), new_point in zip(old_points_ui, new_points_ui):
|
||||||
if old_point != new_point:
|
if old_point != new_point:
|
||||||
differences.append((index, old_point, new_point))
|
#print(old_point)
|
||||||
|
differences.append((old_index, old_point, new_point))
|
||||||
|
|
||||||
return differences
|
return differences
|
||||||
|
|
||||||
@ -266,13 +314,20 @@ class SketchWidget(QWidget):
|
|||||||
# print("Initial slv_points_main:", self.slv_points_main)
|
# print("Initial slv_points_main:", self.slv_points_main)
|
||||||
print("Change list:", point_list)
|
print("Change list:", point_list)
|
||||||
|
|
||||||
if len(point_list) > 0:
|
"""for point in point_list:
|
||||||
|
new = Point2D(point.x(), point.y())
|
||||||
|
self.sketch.points.append(new)"""
|
||||||
|
|
||||||
|
if len(point_list) > 1:
|
||||||
for tbu_points_idx in point_list:
|
for tbu_points_idx in point_list:
|
||||||
# Each tbu_points_idx is a tuple: (index, old_point, new_point)
|
# Each tbu_points_idx is a tuple: (index, old_point, new_point)
|
||||||
index, old_point, new_point = tbu_points_idx
|
index, old_point, new_point = tbu_points_idx
|
||||||
|
|
||||||
# Update the point in slv_points_main
|
# Update the point in slv_points_main
|
||||||
self.sketch.points[index].ui_point = new_point
|
self.sketch.points[index].ui_point = new_point
|
||||||
|
|
||||||
|
"""for points in self.sketch.points:
|
||||||
|
print(points.ui_point)"""
|
||||||
# Print updated state
|
# Print updated state
|
||||||
# print("Updated slv_points_main:", self.slv_points_main)
|
# print("Updated slv_points_main:", self.slv_points_main)
|
||||||
|
|
||||||
@ -291,7 +346,7 @@ class SketchWidget(QWidget):
|
|||||||
if event.button() == Qt.LeftButton and not self.mouse_mode:
|
if event.button() == Qt.LeftButton and not self.mouse_mode:
|
||||||
self.drag_buffer[1] = local_event_pos
|
self.drag_buffer[1] = local_event_pos
|
||||||
|
|
||||||
print("Le main buffer", self.drag_buffer)
|
#print("Le main buffer", self.drag_buffer)
|
||||||
|
|
||||||
if not None in self.main_buffer and len(self.main_buffer) == 2:
|
if not None in self.main_buffer and len(self.main_buffer) == 2:
|
||||||
entry = self.drag_buffer[0]
|
entry = self.drag_buffer[0]
|
||||||
@ -300,9 +355,9 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
self.sketch.solve()
|
self.sketch.solve()
|
||||||
|
|
||||||
points_need_update = self.check_all_points()
|
#points_need_update = self.check_all_points()
|
||||||
self.update_ui_points(points_need_update)
|
#self.update_ui_points(points_need_update)
|
||||||
self.check_all_lines_and_update(points_need_update)
|
#self.check_all_lines_and_update(points_need_update)
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
self.drag_buffer = [None, None]
|
self.drag_buffer = [None, None]
|
||||||
@ -315,6 +370,7 @@ class SketchWidget(QWidget):
|
|||||||
self.drag_buffer[0] = self.get_handle_from_ui_point(self.hovered_point)
|
self.drag_buffer[0] = self.get_handle_from_ui_point(self.hovered_point)
|
||||||
|
|
||||||
if event.button() == Qt.RightButton and self.mouse_mode:
|
if event.button() == Qt.RightButton and self.mouse_mode:
|
||||||
|
self.constrain_done.emit()
|
||||||
self.reset_buffers()
|
self.reset_buffers()
|
||||||
|
|
||||||
if event.button() == Qt.LeftButton and self.mouse_mode == "line":
|
if event.button() == Qt.LeftButton and self.mouse_mode == "line":
|
||||||
@ -329,6 +385,10 @@ class SketchWidget(QWidget):
|
|||||||
v = clicked_pos.y()
|
v = clicked_pos.y()
|
||||||
|
|
||||||
point = Point2D(u,v)
|
point = Point2D(u,v)
|
||||||
|
print("construct", self.is_construct )
|
||||||
|
# Construction mode
|
||||||
|
point.is_helper = self.is_construct
|
||||||
|
|
||||||
self.sketch.add_point(point)
|
self.sketch.add_point(point)
|
||||||
|
|
||||||
self.line_draw_buffer[0] = point
|
self.line_draw_buffer[0] = point
|
||||||
@ -337,17 +397,25 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
u = clicked_pos.x()
|
u = clicked_pos.x()
|
||||||
v = clicked_pos.y()
|
v = clicked_pos.y()
|
||||||
|
print("construct", self.is_construct)
|
||||||
point = Point2D(u, v)
|
point = Point2D(u, v)
|
||||||
|
|
||||||
|
# Construction mode
|
||||||
|
point.is_helper = self.is_construct
|
||||||
|
|
||||||
self.sketch.add_point(point)
|
self.sketch.add_point(point)
|
||||||
|
|
||||||
self.line_draw_buffer[1] = point
|
self.line_draw_buffer[1] = point
|
||||||
|
|
||||||
print("Buffer state", self.line_draw_buffer)
|
#print("Buffer state", self.line_draw_buffer)
|
||||||
|
|
||||||
if self.line_draw_buffer[0] and self.line_draw_buffer[1]:
|
if self.line_draw_buffer[0] and self.line_draw_buffer[1]:
|
||||||
|
|
||||||
line = Line2D(self.line_draw_buffer[0], self.line_draw_buffer[1])
|
line = Line2D(self.line_draw_buffer[0], self.line_draw_buffer[1])
|
||||||
|
|
||||||
|
# Construction mode
|
||||||
|
line.is_helper = self.is_construct
|
||||||
|
|
||||||
self.sketch.add_line(line)
|
self.sketch.add_line(line)
|
||||||
|
|
||||||
# Reset the buffer for the next line segment
|
# Reset the buffer for the next line segment
|
||||||
@ -367,7 +435,7 @@ class SketchWidget(QWidget):
|
|||||||
self.main_buffer[1] = self.get_handle_from_ui_point(self.hovered_point)
|
self.main_buffer[1] = self.get_handle_from_ui_point(self.hovered_point)
|
||||||
|
|
||||||
if self.main_buffer[0] and self.main_buffer[1]:
|
if self.main_buffer[0] and self.main_buffer[1]:
|
||||||
print("buf", self.main_buffer)
|
# print("buf", self.main_buffer)
|
||||||
|
|
||||||
self.sketch.coincident(self.main_buffer[0], self.main_buffer[1], self.sketch.wp)
|
self.sketch.coincident(self.main_buffer[0], self.main_buffer[1], self.sketch.wp)
|
||||||
|
|
||||||
@ -387,7 +455,7 @@ class SketchWidget(QWidget):
|
|||||||
self.main_buffer = [None, None]
|
self.main_buffer = [None, None]
|
||||||
|
|
||||||
if event.button() == Qt.LeftButton and self.mouse_mode == "pt_line":
|
if event.button() == Qt.LeftButton and self.mouse_mode == "pt_line":
|
||||||
print("ptline")
|
#print("ptline")
|
||||||
line_selected = None
|
line_selected = None
|
||||||
|
|
||||||
if self.hovered_point and not self.main_buffer[1]:
|
if self.hovered_point and not self.main_buffer[1]:
|
||||||
@ -418,9 +486,10 @@ class SketchWidget(QWidget):
|
|||||||
self.main_buffer = [None, None]
|
self.main_buffer = [None, None]
|
||||||
|
|
||||||
if event.button() == Qt.LeftButton and self.mouse_mode == "pb_con_mid":
|
if event.button() == Qt.LeftButton and self.mouse_mode == "pb_con_mid":
|
||||||
print("ptline")
|
#print("ptline")
|
||||||
line_selected = None
|
line_selected = None
|
||||||
|
|
||||||
|
|
||||||
if self.hovered_point and not self.main_buffer[1]:
|
if self.hovered_point and not self.main_buffer[1]:
|
||||||
self.main_buffer[0] = self.get_handle_from_ui_point(self.hovered_point)
|
self.main_buffer[0] = self.get_handle_from_ui_point(self.hovered_point)
|
||||||
|
|
||||||
@ -433,6 +502,12 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
if self.sketch.solve() == ResultFlag.OKAY:
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
|
for idx, line in enumerate(self.sketch.lines):
|
||||||
|
# print(line.crd1.ui_point)
|
||||||
|
if self.is_point_on_line(local_event_pos, line.crd1.ui_point, line.crd2.ui_point):
|
||||||
|
self.sketch.lines[idx].constraints.append("mid")
|
||||||
|
print(self.sketch.lines[idx].constraints)
|
||||||
|
|
||||||
|
|
||||||
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
print("Solve_failed - Converge")
|
print("Solve_failed - Converge")
|
||||||
@ -450,12 +525,21 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
line_selected = self.get_line_handle_from_ui_point(local_event_pos)
|
line_selected = self.get_line_handle_from_ui_point(local_event_pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if line_selected:
|
if line_selected:
|
||||||
self.sketch.horizontal(line_selected, self.sketch.wp)
|
self.sketch.horizontal(line_selected, self.sketch.wp)
|
||||||
|
|
||||||
if self.sketch.solve() == ResultFlag.OKAY:
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
|
|
||||||
|
# Add succesful constraint to constrain draw list so it gets drawn in paint function
|
||||||
|
for idx, line in enumerate(self.sketch.lines):
|
||||||
|
#print(line.crd1.ui_point)
|
||||||
|
if self.is_point_on_line(local_event_pos, line.crd1.ui_point, line.crd2.ui_point):
|
||||||
|
self.sketch.lines[idx].constraints.append("hrz")
|
||||||
|
#print(self.sketch.lines[idx].constraints)
|
||||||
|
|
||||||
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
print("Solve_failed - Converge")
|
print("Solve_failed - Converge")
|
||||||
|
|
||||||
@ -473,6 +557,11 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
if self.sketch.solve() == ResultFlag.OKAY:
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
|
for idx, line in enumerate(self.sketch.lines):
|
||||||
|
# print(line.crd1.ui_point)
|
||||||
|
if self.is_point_on_line(local_event_pos, line.crd1.ui_point, line.crd2.ui_point):
|
||||||
|
self.sketch.lines[idx].constraints.append("vrt")
|
||||||
|
# print(self.sketch.lines[idx].constraints)
|
||||||
|
|
||||||
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
print("Solve_failed - Converge")
|
print("Solve_failed - Converge")
|
||||||
@ -490,7 +579,7 @@ class SketchWidget(QWidget):
|
|||||||
e2 = None
|
e2 = None
|
||||||
|
|
||||||
if self.hovered_point:
|
if self.hovered_point:
|
||||||
print("buf point")
|
# print("buf point")
|
||||||
# Get the point as UI point as buffer
|
# Get the point as UI point as buffer
|
||||||
self.main_buffer[0] = self.hovered_point
|
self.main_buffer[0] = self.hovered_point
|
||||||
|
|
||||||
@ -514,6 +603,11 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
if self.sketch.solve() == ResultFlag.OKAY:
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
|
for idx, line in enumerate(self.sketch.lines):
|
||||||
|
# print(line.crd1.ui_point)
|
||||||
|
if self.is_point_on_line(local_event_pos, line.crd1.ui_point, line.crd2.ui_point):
|
||||||
|
if "dist" not in self.sketch.lines[idx].constraints:
|
||||||
|
self.sketch.lines[idx].constraints.append("dst")
|
||||||
|
|
||||||
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
print("Solve_failed - Converge")
|
print("Solve_failed - Converge")
|
||||||
@ -532,6 +626,8 @@ class SketchWidget(QWidget):
|
|||||||
self.update_ui_points(points_need_update)
|
self.update_ui_points(points_need_update)
|
||||||
self.check_all_lines_and_update(points_need_update)
|
self.check_all_lines_and_update(points_need_update)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def mouseMoveEvent(self, event):
|
def mouseMoveEvent(self, event):
|
||||||
@ -540,7 +636,7 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
closest_point = None
|
closest_point = None
|
||||||
min_distance = float('inf')
|
min_distance = float('inf')
|
||||||
threshold = 10 # Distance threshold for highlighting
|
threshold = 15 # Distance threshold for highlighting
|
||||||
|
|
||||||
if self.mouse_mode == "line" and self.line_draw_buffer[0]:
|
if self.mouse_mode == "line" and self.line_draw_buffer[0]:
|
||||||
# Update the current cursor position as the second point
|
# Update the current cursor position as the second point
|
||||||
@ -562,7 +658,7 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
if closest_point != self.hovered_point:
|
if closest_point != self.hovered_point:
|
||||||
self.hovered_point = closest_point
|
self.hovered_point = closest_point
|
||||||
print(self.hovered_point)
|
#print(self.hovered_point)
|
||||||
|
|
||||||
for line in self.sketch.lines:
|
for line in self.sketch.lines:
|
||||||
p1 = line.crd1.ui_point
|
p1 = line.crd1.ui_point
|
||||||
@ -571,11 +667,14 @@ class SketchWidget(QWidget):
|
|||||||
if self.is_point_on_line(local_event_pos, p1, p2):
|
if self.is_point_on_line(local_event_pos, p1, p2):
|
||||||
self.selected_line = p1, p2
|
self.selected_line = p1, p2
|
||||||
|
|
||||||
# Midpointsnap only in drawer not solver
|
if self.snap_mode.get("mpoint"):
|
||||||
mid = self.calculate_midpoint(p1, p2)
|
# Midpointsnap only in drawer not solver
|
||||||
distance = (local_event_pos - mid).manhattanLength()
|
mid = self.calculate_midpoint(p1, p2)
|
||||||
if distance < threshold and distance < min_distance:
|
distance = (local_event_pos - mid).manhattanLength()
|
||||||
self.hovered_point = mid
|
if distance < threshold and distance < min_distance:
|
||||||
|
self.hovered_point = mid
|
||||||
|
break
|
||||||
|
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.selected_line = None
|
self.selected_line = None
|
||||||
@ -678,6 +777,103 @@ class SketchWidget(QWidget):
|
|||||||
widget_y = -point.y()
|
widget_y = -point.y()
|
||||||
return QPoint(int(widget_x), int(widget_y))
|
return QPoint(int(widget_x), int(widget_y))
|
||||||
|
|
||||||
|
def draw_measurement(self,painter, start_point, end_point):
|
||||||
|
|
||||||
|
pen_normal = QPen(Qt.gray)
|
||||||
|
pen_normal.setWidthF(2 / self.zoom)
|
||||||
|
|
||||||
|
pen_planned = QPen(Qt.gray)
|
||||||
|
pen_planned.setStyle(Qt.PenStyle.DotLine)
|
||||||
|
pen_planned.setWidthF(2 / self.zoom)
|
||||||
|
|
||||||
|
pen_construct = QPen(Qt.cyan)
|
||||||
|
pen_construct.setStyle(Qt.PenStyle.DotLine)
|
||||||
|
pen_construct.setWidthF(1 / self.zoom)
|
||||||
|
|
||||||
|
pen_solver = QPen(Qt.green)
|
||||||
|
pen_solver.setWidthF(2 / self.zoom)
|
||||||
|
|
||||||
|
pen_text = QPen(Qt.white)
|
||||||
|
pen_text.setWidthF(1 / self.zoom)
|
||||||
|
|
||||||
|
# Calculate the direction of the line
|
||||||
|
dx = end_point.x() - start_point.x()
|
||||||
|
dy = end_point.y() - start_point.y()
|
||||||
|
|
||||||
|
# Swap and negate to get a perpendicular vector
|
||||||
|
perp_dx = -dy
|
||||||
|
perp_dy = dx
|
||||||
|
|
||||||
|
# Normalize the perpendicular vector
|
||||||
|
length = (perp_dx ** 2 + perp_dy ** 2) ** 0.5
|
||||||
|
if length == 0: # Prevent division by zero
|
||||||
|
return
|
||||||
|
perp_dx /= length
|
||||||
|
perp_dy /= length
|
||||||
|
|
||||||
|
# Fixed length for the perpendicular lines
|
||||||
|
fixed_length = 40 # Adjust as needed
|
||||||
|
half_length = fixed_length # fixed_length / 2
|
||||||
|
|
||||||
|
# Calculate endpoints for the perpendicular line at the start
|
||||||
|
start_perp_start_x = start_point.x() + perp_dx
|
||||||
|
start_perp_start_y = start_point.y() + perp_dy
|
||||||
|
|
||||||
|
start_perp_end_x = start_point.x() + perp_dx * half_length * (1 / self.zoom)
|
||||||
|
start_perp_end_y = start_point.y() + perp_dy * half_length * (1 / self.zoom)
|
||||||
|
|
||||||
|
start_perp_end_x_conn_line = start_point.x() + perp_dx * half_length * 0.75 * (1 / self.zoom)
|
||||||
|
start_perp_end_y_conn_line = start_point.y() + perp_dy * half_length * 0.75 * (1 / self.zoom)
|
||||||
|
|
||||||
|
# Draw the perpendicular line at the start
|
||||||
|
painter.setPen(pen_construct) # Different color for the perpendicular line
|
||||||
|
painter.drawLine(
|
||||||
|
QPointF(start_perp_start_x, start_perp_start_y),
|
||||||
|
QPointF(start_perp_end_x, start_perp_end_y)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Calculate endpoints for the perpendicular line at the end
|
||||||
|
end_perp_start_x = end_point.x() + perp_dx
|
||||||
|
end_perp_start_y = end_point.y() + perp_dy
|
||||||
|
|
||||||
|
end_perp_end_x = end_point.x() + perp_dx * half_length * (1 / self.zoom)
|
||||||
|
end_perp_end_y = end_point.y() + perp_dy * half_length * (1 / self.zoom)
|
||||||
|
|
||||||
|
end_perp_end_x_conn_line = end_point.x() + perp_dx * half_length * .75 * (1 / self.zoom)
|
||||||
|
end_perp_end_y_conn_line = end_point.y() + perp_dy * half_length * .75 * (1 / self.zoom)
|
||||||
|
|
||||||
|
# Draw the perpendicular line at the end
|
||||||
|
painter.drawLine(
|
||||||
|
QPointF(end_perp_start_x, end_perp_start_y),
|
||||||
|
QPointF(end_perp_end_x, end_perp_end_y)
|
||||||
|
)
|
||||||
|
|
||||||
|
painter.drawLine(
|
||||||
|
QPointF(end_perp_end_x_conn_line, end_perp_end_y_conn_line),
|
||||||
|
QPointF(start_perp_end_x_conn_line, start_perp_end_y_conn_line)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Save painter state
|
||||||
|
painter.save()
|
||||||
|
painter.setPen(pen_text)
|
||||||
|
|
||||||
|
# Calculate the distance and midpoint
|
||||||
|
dis = self.distance(start_point, end_point)
|
||||||
|
mid = self.calculate_midpoint(QPointF(start_perp_end_x_conn_line, start_perp_end_y_conn_line),
|
||||||
|
QPointF(end_perp_end_x_conn_line, end_perp_end_y_conn_line))
|
||||||
|
|
||||||
|
# mid = self.calculate_midpoint(start_point, end_point)
|
||||||
|
|
||||||
|
# Transform for text
|
||||||
|
painter.translate(mid.x(), mid.y()) # Move to the midpoint
|
||||||
|
painter.scale(1, -1) # Flip y-axis back to make text readable
|
||||||
|
|
||||||
|
# Draw the text
|
||||||
|
painter.drawText(0, 0, str(round(dis, 2))) # Draw text at transformed position
|
||||||
|
|
||||||
|
# Restore painter state
|
||||||
|
painter.restore()
|
||||||
|
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event):
|
||||||
painter = QPainter(self)
|
painter = QPainter(self)
|
||||||
painter.setRenderHint(QPainter.Antialiasing)
|
painter.setRenderHint(QPainter.Antialiasing)
|
||||||
@ -700,6 +896,10 @@ class SketchWidget(QWidget):
|
|||||||
pen_normal = QPen(Qt.gray)
|
pen_normal = QPen(Qt.gray)
|
||||||
pen_normal.setWidthF(2 / self.zoom)
|
pen_normal.setWidthF(2 / self.zoom)
|
||||||
|
|
||||||
|
pen_planned = QPen(Qt.gray)
|
||||||
|
pen_planned.setStyle(Qt.PenStyle.DotLine)
|
||||||
|
pen_planned.setWidthF(2 / self.zoom)
|
||||||
|
|
||||||
pen_construct = QPen(Qt.cyan)
|
pen_construct = QPen(Qt.cyan)
|
||||||
pen_construct.setStyle(Qt.PenStyle.DotLine)
|
pen_construct.setStyle(Qt.PenStyle.DotLine)
|
||||||
pen_construct.setWidthF(1 / self.zoom)
|
pen_construct.setWidthF(1 / self.zoom)
|
||||||
@ -726,26 +926,10 @@ class SketchWidget(QWidget):
|
|||||||
if self.mouse_mode == "line" and self.line_draw_buffer[0] and self.dynamic_line_end is not None:
|
if self.mouse_mode == "line" and self.line_draw_buffer[0] and self.dynamic_line_end is not None:
|
||||||
start_point = self.line_draw_buffer[0].ui_point
|
start_point = self.line_draw_buffer[0].ui_point
|
||||||
end_point = self.dynamic_line_end
|
end_point = self.dynamic_line_end
|
||||||
painter.setPen(Qt.red) # Use a different color for the dynamic line
|
painter.setPen(pen_planned) # Use a different color for the dynamic line
|
||||||
painter.drawLine(start_point, end_point)
|
painter.drawLine(start_point, end_point)
|
||||||
|
|
||||||
# Save painter state
|
self.draw_measurement(painter, start_point, end_point)
|
||||||
painter.save()
|
|
||||||
painter.setPen(pen_text)
|
|
||||||
|
|
||||||
# Calculate the distance and midpoint
|
|
||||||
dis = self.distance(start_point, end_point)
|
|
||||||
mid = self.calculate_midpoint(start_point, end_point)
|
|
||||||
|
|
||||||
# Transform for text
|
|
||||||
painter.translate(mid.x(), mid.y()) # Move to the midpoint
|
|
||||||
painter.scale(1, -1) # Flip y-axis back to make text readable
|
|
||||||
|
|
||||||
# Draw the text
|
|
||||||
painter.drawText(0, 0, str(round(dis, 2))) # Draw text at transformed position
|
|
||||||
|
|
||||||
# Restore painter state
|
|
||||||
painter.restore()
|
|
||||||
|
|
||||||
for line in self.sketch.lines:
|
for line in self.sketch.lines:
|
||||||
if line.is_helper:
|
if line.is_helper:
|
||||||
@ -759,6 +943,17 @@ class SketchWidget(QWidget):
|
|||||||
p2 = line.crd2.ui_point
|
p2 = line.crd2.ui_point
|
||||||
painter.drawLine(p1, p2)
|
painter.drawLine(p1, p2)
|
||||||
|
|
||||||
|
if not self.selected_line:
|
||||||
|
|
||||||
|
painter.save()
|
||||||
|
midp = self.calculate_midpoint(p1, p2)
|
||||||
|
painter.translate(midp)
|
||||||
|
painter.scale(1, -1)
|
||||||
|
|
||||||
|
for i, text in enumerate(line.constraints):
|
||||||
|
painter.drawText(0, i * 15, f"> {text} <")
|
||||||
|
painter.restore()
|
||||||
|
|
||||||
# Draw all solver points
|
# Draw all solver points
|
||||||
if self.sketch.entity_len():
|
if self.sketch.entity_len():
|
||||||
painter.setPen(pen_solver)
|
painter.setPen(pen_solver)
|
||||||
@ -782,6 +977,9 @@ class SketchWidget(QWidget):
|
|||||||
painter.setPen(QPen(Qt.red, 2 / self.zoom))
|
painter.setPen(QPen(Qt.red, 2 / self.zoom))
|
||||||
painter.drawLine(p1, p2)
|
painter.drawLine(p1, p2)
|
||||||
|
|
||||||
|
self.draw_measurement(painter, p1, p2)
|
||||||
|
|
||||||
|
|
||||||
"""for cross in self.sketch.proj_points:
|
"""for cross in self.sketch.proj_points:
|
||||||
self.draw_cross(painter, cross, 10 / self.zoom)
|
self.draw_cross(painter, cross, 10 / self.zoom)
|
||||||
|
|
||||||
@ -825,6 +1023,9 @@ class Line2D:
|
|||||||
|
|
||||||
# Construction Geometry
|
# Construction Geometry
|
||||||
self.is_helper: bool = False
|
self.is_helper: bool = False
|
||||||
|
# String list with applied constraints
|
||||||
|
self.constraints: list = []
|
||||||
|
|
||||||
|
|
||||||
class Sketch2d(SolverSystem):
|
class Sketch2d(SolverSystem):
|
||||||
"""
|
"""
|
||||||
|
33
gui.ui
33
gui.ui
@ -733,6 +733,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoExclusive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
@ -813,6 +816,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoExclusive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -836,9 +842,9 @@
|
|||||||
<enum>QTabWidget::South</enum>
|
<enum>QTabWidget::South</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="">
|
<widget class="QWidget" name="snaps">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Setg 1</string>
|
<string>Setg 1</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
@ -882,6 +888,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoExclusive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0" colspan="2">
|
<item row="4" column="0" colspan="2">
|
||||||
@ -919,6 +928,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoExclusive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
@ -929,6 +941,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoExclusive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
@ -949,6 +964,12 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Pnt</string>
|
<string>Pnt</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="autoExclusive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
@ -959,6 +980,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoExclusive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
@ -969,6 +993,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoExclusive">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -976,7 +1003,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="">
|
<widget class="QWidget" name="settings">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Setg 2</string>
|
<string>Setg 2</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
16
license.md
Normal file
16
license.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Copyright (C) 2025 Thomas Herrmann
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
106
main.py
106
main.py
@ -120,13 +120,13 @@ class MainWindow(QMainWindow):
|
|||||||
self.ui.pb_flip_face.pressed.connect(self.on_flip_face)
|
self.ui.pb_flip_face.pressed.connect(self.on_flip_face)
|
||||||
|
|
||||||
###Modes
|
###Modes
|
||||||
self.ui.pb_linetool.pressed.connect(self.act_line_mode)
|
self.ui.pb_linetool.clicked.connect(self.sketchWidget.act_line_mode)
|
||||||
self.ui.pb_con_ptpt.pressed.connect(self.act_constrain_pt_pt_mode)
|
self.ui.pb_con_ptpt.clicked.connect(self.sketchWidget.act_constrain_pt_pt_mode)
|
||||||
self.ui.pb_con_line.pressed.connect(self.act_constrain_pt_line_mode)
|
self.ui.pb_con_line.clicked.connect(self.sketchWidget.act_constrain_pt_line_mode)
|
||||||
self.ui.pb_con_horiz.pressed.connect(self.act_constrain_horiz_line_mode)
|
self.ui.pb_con_horiz.clicked.connect(self.sketchWidget.act_constrain_horiz_line_mode)
|
||||||
self.ui.pb_con_vert.pressed.connect(self.act_constrain_vert_line_mode)
|
self.ui.pb_con_vert.clicked.connect(self.sketchWidget.act_constrain_vert_line_mode)
|
||||||
self.ui.pb_con_dist.pressed.connect(self.act_constrain_distance_mode)
|
self.ui.pb_con_dist.clicked.connect(self.sketchWidget.act_constrain_distance_mode)
|
||||||
self.ui.pb_con_mid.pressed.connect(self.act_constrain_mid_point_mode)
|
self.ui.pb_con_mid.clicked.connect(self.sketchWidget.act_constrain_mid_point_mode)
|
||||||
|
|
||||||
### Operations
|
### Operations
|
||||||
self.ui.pb_extrdop.pressed.connect(self.send_extrude)
|
self.ui.pb_extrdop.pressed.connect(self.send_extrude)
|
||||||
@ -137,12 +137,18 @@ class MainWindow(QMainWindow):
|
|||||||
self.setFocusPolicy(Qt.StrongFocus)
|
self.setFocusPolicy(Qt.StrongFocus)
|
||||||
|
|
||||||
self.send_command.connect(self.custom_3D_Widget.on_receive_command)
|
self.send_command.connect(self.custom_3D_Widget.on_receive_command)
|
||||||
|
|
||||||
self.ui.actionNew_Project.triggered.connect(self.new_project)
|
self.ui.actionNew_Project.triggered.connect(self.new_project)
|
||||||
|
self.ui.pb_enable_construct.clicked.connect(self.sketchWidget.on_construct_change)
|
||||||
self.project = Project()
|
self.project = Project()
|
||||||
self.new_project()
|
self.new_project()
|
||||||
|
|
||||||
|
### SNAPS
|
||||||
|
|
||||||
|
self.ui.pb_snap_midp.toggled.connect(lambda checked: self.sketchWidget.on_snap_mode_change("mpoint", checked))
|
||||||
|
self.ui.pb_snap_horiz.toggled.connect(lambda checked: self.sketchWidget.on_snap_mode_change("horiz", checked))
|
||||||
|
self.ui.pb_snap_vert.toggled.connect(lambda checked: self.sketchWidget.on_snap_mode_change("vert", checked))
|
||||||
|
self.ui.pb_snap_angle.toggled.connect(lambda checked: self.sketchWidget.on_snap_mode_change("angle", checked))
|
||||||
|
self.ui.pb_enable_snap.toggled.connect(lambda checked: self.sketchWidget.on_snap_mode_change("point", checked))
|
||||||
### COMPOS
|
### COMPOS
|
||||||
### COMPOS
|
### COMPOS
|
||||||
|
|
||||||
@ -156,7 +162,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.project.timeline = timeline
|
self.project.timeline = timeline
|
||||||
self.new_component()
|
self.new_component()
|
||||||
|
|
||||||
|
|
||||||
def new_component(self):
|
def new_component(self):
|
||||||
print("Creating a new component...")
|
print("Creating a new component...")
|
||||||
|
|
||||||
@ -270,7 +275,7 @@ class MainWindow(QMainWindow):
|
|||||||
sketch.original_sketch = sketch_from_widget
|
sketch.original_sketch = sketch_from_widget
|
||||||
|
|
||||||
#Get parameters
|
#Get parameters
|
||||||
points = sketch_from_widget.points
|
points = [point for point in sketch_from_widget.points if hasattr(point, 'is_helper') and not point.is_helper]
|
||||||
|
|
||||||
sketch.convert_points_for_sdf(points)
|
sketch.convert_points_for_sdf(points)
|
||||||
sketch.id = sketch_from_widget.id
|
sketch.id = sketch_from_widget.id
|
||||||
@ -280,7 +285,7 @@ class MainWindow(QMainWindow):
|
|||||||
# Register sketch to timeline
|
# Register sketch to timeline
|
||||||
### Add selection compo here
|
### Add selection compo here
|
||||||
compo_id = self.get_activated_compo()
|
compo_id = self.get_activated_compo()
|
||||||
print("newsketch_name", sketch.id)
|
#print("newsketch_name", sketch.id)
|
||||||
self.project.timeline[compo_id].sketches[sketch.id] = sketch
|
self.project.timeline[compo_id].sketches[sketch.id] = sketch
|
||||||
|
|
||||||
# Add Item to slection menu
|
# Add Item to slection menu
|
||||||
@ -294,6 +299,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.ui.sketch_list.setCurrentItem(items)
|
self.ui.sketch_list.setCurrentItem(items)
|
||||||
|
|
||||||
def on_compo_change(self):
|
def on_compo_change(self):
|
||||||
|
'''This function redraws the sdf and helper mesh from available bodies and adds the names back to the list entries'''
|
||||||
self.custom_3D_Widget.clear_body_actors()
|
self.custom_3D_Widget.clear_body_actors()
|
||||||
self.custom_3D_Widget.clear_actors_interactor()
|
self.custom_3D_Widget.clear_actors_interactor()
|
||||||
self.custom_3D_Widget.clear_actors_projection()
|
self.custom_3D_Widget.clear_actors_projection()
|
||||||
@ -303,27 +309,27 @@ class MainWindow(QMainWindow):
|
|||||||
self.ui.sketch_list.clear()
|
self.ui.sketch_list.clear()
|
||||||
self.ui.body_list.clear()
|
self.ui.body_list.clear()
|
||||||
|
|
||||||
print("id", compo_id)
|
#print("id", compo_id)
|
||||||
print("sketch_registry", self.project.timeline[compo_id].sketches)
|
#print("sketch_registry", self.project.timeline[compo_id].sketches)
|
||||||
|
|
||||||
for sketch in self.project.timeline[compo_id].sketches:
|
for sketch in self.project.timeline[compo_id].sketches:
|
||||||
print(sketch)
|
#print(sketch)
|
||||||
self.ui.sketch_list.addItem(sketch)
|
self.ui.sketch_list.addItem(sketch)
|
||||||
|
|
||||||
for body in self.project.timeline[compo_id].bodies:
|
for body in self.project.timeline[compo_id].bodies:
|
||||||
self.ui.body_list.addItem(body)
|
self.ui.body_list.addItem(body)
|
||||||
|
|
||||||
if self.project.timeline[compo_id].bodies:
|
if self.project.timeline[compo_id].bodies:
|
||||||
item = self.ui.body_list.findItems(body , Qt.MatchExactly)[0]
|
item = self.ui.body_list.findItems(body , Qt.MatchExactly)[0]
|
||||||
self.ui.body_list.setCurrentItem(item)
|
self.ui.body_list.setCurrentItem(item)
|
||||||
self.draw_mesh()
|
self.draw_mesh()
|
||||||
|
|
||||||
selected = self.ui.body_list.currentItem()
|
selected = self.ui.body_list.currentItem()
|
||||||
name = selected.text()
|
name = selected.text()
|
||||||
|
|
||||||
edges = self.project.timeline[compo_id].bodies[name].interactor.edges
|
edges = self.project.timeline[compo_id].bodies[name].interactor.edges
|
||||||
offset_vec = self.project.timeline[compo_id].bodies[name].interactor.offset_vector
|
offset_vec = self.project.timeline[compo_id].bodies[name].interactor.offset_vector
|
||||||
self.custom_3D_Widget.load_interactor_mesh(edges, offset_vec)
|
self.custom_3D_Widget.load_interactor_mesh(edges, offset_vec)
|
||||||
|
|
||||||
def edit_sketch(self):
|
def edit_sketch(self):
|
||||||
selected = self.ui.sketch_list.currentItem()
|
selected = self.ui.sketch_list.currentItem()
|
||||||
@ -353,49 +359,6 @@ class MainWindow(QMainWindow):
|
|||||||
def on_flip_face(self):
|
def on_flip_face(self):
|
||||||
self.send_command.emit("flip")
|
self.send_command.emit("flip")
|
||||||
|
|
||||||
def act_line_mode(self):
|
|
||||||
if not self.ui.pb_linetool.isChecked():
|
|
||||||
self.sketchWidget.mouse_mode = 'line'
|
|
||||||
else:
|
|
||||||
self.sketchWidget.mouse_mode = None
|
|
||||||
self.sketchWidget.line_draw_buffer = [None, None]
|
|
||||||
|
|
||||||
def act_constrain_pt_pt_mode(self):
|
|
||||||
if not self.ui.pb_con_ptpt.isChecked():
|
|
||||||
self.sketchWidget.mouse_mode = 'pt_pt'
|
|
||||||
else:
|
|
||||||
self.sketchWidget.mouse_mode = None
|
|
||||||
|
|
||||||
def act_constrain_pt_line_mode(self):
|
|
||||||
if not self.ui.pb_con_line.isChecked():
|
|
||||||
self.sketchWidget.mouse_mode = 'pt_line'
|
|
||||||
else:
|
|
||||||
self.sketchWidget.mouse_mode = None
|
|
||||||
|
|
||||||
def act_constrain_horiz_line_mode(self):
|
|
||||||
if not self.ui.pb_con_horiz.isChecked():
|
|
||||||
self.sketchWidget.mouse_mode = 'horiz'
|
|
||||||
else:
|
|
||||||
self.sketchWidget.mouse_mode = None
|
|
||||||
|
|
||||||
def act_constrain_vert_line_mode(self):
|
|
||||||
if not self.ui.pb_con_vert.isChecked():
|
|
||||||
self.sketchWidget.mouse_mode = 'vert'
|
|
||||||
else:
|
|
||||||
self.sketchWidget.mouse_mode = None
|
|
||||||
|
|
||||||
def act_constrain_distance_mode(self):
|
|
||||||
if not self.ui.pb_con_dist.isChecked():
|
|
||||||
self.sketchWidget.mouse_mode = 'distance'
|
|
||||||
else:
|
|
||||||
self.sketchWidget.mouse_mode = None
|
|
||||||
|
|
||||||
def act_constrain_mid_point_mode(self):
|
|
||||||
if not self.ui.pb_con_mid.isChecked():
|
|
||||||
self.sketchWidget.mouse_mode = 'pb_con_mid'
|
|
||||||
else:
|
|
||||||
self.sketchWidget.mouse_mode = None
|
|
||||||
|
|
||||||
def draw_op_complete(self):
|
def draw_op_complete(self):
|
||||||
# safely disable the line modes
|
# safely disable the line modes
|
||||||
self.ui.pb_linetool.setChecked(False)
|
self.ui.pb_linetool.setChecked(False)
|
||||||
@ -420,7 +383,7 @@ class MainWindow(QMainWindow):
|
|||||||
model_data = vesta.generate_mesh_from_sdf(model, resolution=64, threshold=0)
|
model_data = vesta.generate_mesh_from_sdf(model, resolution=64, threshold=0)
|
||||||
|
|
||||||
vertices, faces = model_data
|
vertices, faces = model_data
|
||||||
vesta.save_mesh_as_stl(vertices, faces, 'test.stl')
|
#vesta.save_mesh_as_stl(vertices, faces, 'test.stl')
|
||||||
self.custom_3D_Widget.render_from_points_direct_with_faces(vertices, faces)
|
self.custom_3D_Widget.render_from_points_direct_with_faces(vertices, faces)
|
||||||
|
|
||||||
def on_item_changed(self, current_item, previous_item):
|
def on_item_changed(self, current_item, previous_item):
|
||||||
@ -464,8 +427,9 @@ class MainWindow(QMainWindow):
|
|||||||
#print(sketch)
|
#print(sketch)
|
||||||
points = sketch.sdf_points
|
points = sketch.sdf_points
|
||||||
|
|
||||||
|
# detect loop that causes problems in mesh generation
|
||||||
if points[-1] == points[0]:
|
if points[-1] == points[0]:
|
||||||
#detect loop that causes problems in mesh generation
|
print("overlap")
|
||||||
del points[-1]
|
del points[-1]
|
||||||
|
|
||||||
dialog = ExtrudeDialog(self)
|
dialog = ExtrudeDialog(self)
|
||||||
@ -484,8 +448,8 @@ class MainWindow(QMainWindow):
|
|||||||
centroid = self.custom_3D_Widget.centroid
|
centroid = self.custom_3D_Widget.centroid
|
||||||
if centroid is None:
|
if centroid is None:
|
||||||
centroid = [0, 0, 0]
|
centroid = [0, 0, 0]
|
||||||
else:
|
"""else:
|
||||||
centroid = list(centroid)
|
centroid = list(centroid)"""
|
||||||
#print("This centroid ", centroid)
|
#print("This centroid ", centroid)
|
||||||
|
|
||||||
sketch.origin = centroid
|
sketch.origin = centroid
|
||||||
|
102
requirements.txt
102
requirements.txt
@ -1,66 +1,60 @@
|
|||||||
certifi==2024.7.4
|
certifi==2025.1.31
|
||||||
cffi==1.16.0
|
cffi==1.17.1
|
||||||
charset-normalizer==3.3.2
|
charset-normalizer==3.4.1
|
||||||
contourpy==1.2.0
|
contourpy==1.3.1
|
||||||
cycler==0.12.1
|
cycler==0.12.1
|
||||||
fonttools==4.47.0
|
flexcache==0.3
|
||||||
freetype-py==2.4.0
|
flexparser==0.4
|
||||||
|
fonttools==4.56.0
|
||||||
|
freetype-py==2.5.1
|
||||||
hsluv==5.0.4
|
hsluv==5.0.4
|
||||||
idna==3.7
|
idna==3.10
|
||||||
imageio==2.33.1
|
imageio==2.37.0
|
||||||
kiwisolver==1.4.5
|
kiwisolver==1.4.8
|
||||||
lazy_loader==0.3
|
lazy_loader==0.4
|
||||||
markdown-it-py==3.0.0
|
markdown-it-py==3.0.0
|
||||||
matplotlib==3.8.2
|
matplotlib==3.10.1
|
||||||
mdurl==0.1.2
|
mdurl==0.1.2
|
||||||
meshio==5.3.4
|
meshio==5.3.5
|
||||||
names==0.3.0
|
names==0.3.0
|
||||||
networkx==3.2.1
|
networkx==3.4.2
|
||||||
Nuitka==2.2.1
|
Nuitka==2.6.9
|
||||||
numpy==1.26.2
|
numpy==2.2.4
|
||||||
numpy-stl==3.1.1
|
numpy-stl==3.2.0
|
||||||
ordered-set==4.1.0
|
ordered-set==4.1.0
|
||||||
packaging==23.2
|
packaging==24.2
|
||||||
panda3d-gltf==1.2.0
|
panda3d-gltf==1.3.0
|
||||||
panda3d-simplepbr==0.12.0
|
panda3d-simplepbr==0.13.0
|
||||||
Pillow==10.1.0
|
pillow==11.1.0
|
||||||
Pint==0.22
|
Pint==0.24.4
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.7
|
||||||
pooch==1.8.2
|
pooch==1.8.2
|
||||||
pycparser==2.21
|
pycparser==2.22
|
||||||
pygame==2.5.2
|
pygame==2.6.1
|
||||||
Pygments==2.17.2
|
Pygments==2.19.1
|
||||||
PyOpenGL==3.1.7
|
pyparsing==3.2.3
|
||||||
pyparsing==3.1.1
|
PySide6_Essentials==6.8.3
|
||||||
PyQt6==6.7.0
|
python-dateutil==2.9.0.post0
|
||||||
PyQt6-3D==6.7.0
|
|
||||||
PyQt6-3D-Qt6==6.7.0
|
|
||||||
PyQt6-Qt6==6.7.0
|
|
||||||
PyQt6-sip==13.6.0
|
|
||||||
PySide6==6.6.1
|
|
||||||
PySide6-Addons==6.6.1
|
|
||||||
PySide6-Essentials==6.6.1
|
|
||||||
python-dateutil==2.8.2
|
|
||||||
python-solvespace==3.0.8
|
python-solvespace==3.0.8
|
||||||
python-utils==3.8.2
|
python-utils==3.9.1
|
||||||
pyvista==0.43.10
|
pyvista==0.44.2
|
||||||
pyvistaqt==0.11.1
|
pyvistaqt==0.11.2
|
||||||
QtPy==2.4.1
|
QtPy==2.4.3
|
||||||
requests==2.32.3
|
requests==2.32.3
|
||||||
rich==13.7.0
|
rich==13.9.4
|
||||||
scikit-image==0.22.0
|
scikit-image==0.25.2
|
||||||
scipy==1.11.4
|
scipy==1.15.2
|
||||||
scooby==0.10.0
|
scooby==0.10.0
|
||||||
sdfcad @ git+https://gitlab.com/nobodyinperson/sdfCAD@9bd4e9021c6ee7e685ee28e8a3a5d2d2c028190c
|
sdfcad @ git+https://gitlab.com/nobodyinperson/sdfCAD@9bd4e9021c6ee7e685ee28e8a3a5d2d2c028190c
|
||||||
shapely==2.0.4
|
shapely==2.1.0rc1
|
||||||
shiboken6==6.6.1
|
shiboken6==6.8.3
|
||||||
six==1.16.0
|
six==1.17.0
|
||||||
tifffile==2023.12.9
|
tifffile==2025.3.13
|
||||||
trimesh==4.3.2
|
trimesh==4.6.5
|
||||||
tripy==1.0.0
|
tripy==1.0.0
|
||||||
typing_extensions==4.9.0
|
typing_extensions==4.13.0
|
||||||
urllib3==2.2.2
|
urllib3==2.3.0
|
||||||
vispy==0.14.2
|
vispy==0.14.3
|
||||||
vtk==9.3.0
|
vtk==9.4.1
|
||||||
vulkan==1.3.275.0
|
vulkan==1.3.275.1
|
||||||
zstandard==0.22.0
|
zstandard==0.23.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user