Merge Coincident Nodes and Align Meshes, as a pane beside the 3-D view.
Merge follows select, see, set, apply (principle 13). The element
groups are picked in the tree, every place their nodes coincide is
marked in the view, and the tolerance is set here. A click on a mark
leaves that place out of the merge and a second click puts it back;
All and None mark every place or none. Merge then runs the project's
merge_coincident_nodes with the places left out as its exclude.
Leaving places out is how a joint is built from parts meshed
separately, one place at a time, instead of with rigid links.
Align Meshes uses the same pane. Parts meshed separately at element
sizes that do not match have no coincident nodes to merge, so this
step, done before the merge, moves the coarser mesh's nodes onto the
finer mesh's where they meet. The pane shows a reach in place of the
tolerance, each mark is a move (the node, and a line to where it goes),
and Align runs the project's align_meshes.
The pane holds no rules of its own. The window asks the geometry what
the settings would merge (coincident_spots, merge_folds) or move
(align_moves, align_folds), marks it in the view, and shows the
result here.
Classes:
| Name |
Description |
MergePanel |
The tolerance, what it finds, and the Merge button; or, for Align
|
Classes
MergePanel
MergePanel(parent: QWidget | None = None)
Bases: QWidget
The tolerance, what it finds, and the Merge button; or, for Align
Meshes, the reach, the moves and the Align button.
Methods:
| Name |
Description |
open_for |
Set the pane up for kind, 'merge' or 'align': the tolerance
|
value |
The tolerance (or the reach) as typed, in the display unit.
|
set_value |
Set the tolerance (or the reach) as if it were typed.
|
Source code in src/visualdynamics/gui/merge_panel.py
| def __init__(self, parent: QWidget | None = None) -> None:
super().__init__(parent)
self.title: QLabel = QLabel('Merge Coincident Nodes')
grid = panel_grid(self, self.title)
self.tolerance_label: QLabel = QLabel('Tolerance')
self.tolerance: DoubleSpinBox = DoubleSpinBox()
self.tolerance.setDecimals(LENGTH_DECIMALS)
self.tolerance.setRange(0.0, 1e9)
self.tolerance.setToolTip(
'Nodes closer than this are one place, in the display unit')
grid.addWidget(self.tolerance_label, 1, 0)
grid.addWidget(self.tolerance, 1, 1)
self.groups_label: QLabel = QLabel()
self.groups_label.setWordWrap(True)
self.groups_label.setEnabled(False)
grid.addWidget(self.groups_label, 2, 0, 1, 2)
self.reading_label: QLabel = QLabel()
self.reading_label.setWordWrap(True)
grid.addWidget(self.reading_label, 3, 0, 1, 2)
picks = QHBoxLayout()
self.all_button: QPushButton = QPushButton('All')
self.all_button.setToolTip('Mark every place to merge')
self.none_button: QPushButton = QPushButton('None')
self.none_button.setToolTip('Leave every place out, to mark a few '
'by clicking them in the view')
picks.addWidget(self.all_button)
picks.addWidget(self.none_button)
grid.addLayout(picks, 4, 0, 1, 2)
buttons = QHBoxLayout()
self.merge_button: QPushButton = QPushButton('Merge')
self.merge_button.setToolTip('Make the coincident nodes picked one '
'node each')
self.merge_button.setDefault(True)
self.close_button: QPushButton = QPushButton('Close')
self.close_button.setToolTip('Put the pane away without merging')
buttons.addWidget(self.merge_button)
buttons.addWidget(self.close_button)
grid.addLayout(buttons, 5, 0, 1, 2)
grid.setRowStretch(6, 1)
commit_on_enter(self.tolerance)
self.tolerance.valueChanged.connect(lambda _value: self.changed.emit())
self.all_button.clicked.connect(self.all_asked.emit)
self.none_button.clicked.connect(self.none_asked.emit)
self.merge_button.clicked.connect(self.merge_asked.emit)
self.close_button.clicked.connect(self.close_asked.emit)
|
Methods:
open_for
open_for(unit: str, tolerance: float, groups: str, kind: str = 'merge') -> None
Set the pane up for kind, 'merge' or 'align': the tolerance
(or the reach) in the display unit unit, and groups, the
names of the element groups it works on.
Source code in src/visualdynamics/gui/merge_panel.py
| def open_for(self, unit: str, tolerance: float, groups: str,
kind: str = 'merge') -> None:
"""Set the pane up for `kind`, 'merge' or 'align': the tolerance
(or the reach) in the display unit `unit`, and `groups`, the
names of the element groups it works on."""
title, label, tip, button = KINDS[kind]
self.title.setText(title)
self.tolerance_label.setText(f'{label} [{unit}]')
self.tolerance.setToolTip(tip)
self.merge_button.setText(button)
self.all_button.setToolTip(f'Mark every place to {button.lower()}')
self.tolerance.blockSignals(True)
# a step a tenth of the starting tolerance's order, so the
# arrows move it by something that can matter
self.tolerance.setSingleStep(max(tolerance, 1e-6))
self.tolerance.setValue(tolerance)
self.tolerance.blockSignals(False)
self.groups_label.setText(f'Element groups: {groups}')
|
value
The tolerance (or the reach) as typed, in the display unit.
Source code in src/visualdynamics/gui/merge_panel.py
| def value(self) -> float:
"""The tolerance (or the reach) as typed, in the display unit."""
return self.tolerance.value()
|
set_value
set_value(tolerance: float) -> None
Set the tolerance (or the reach) as if it were typed.
changed is emitted, so the window finds the places again.
Source code in src/visualdynamics/gui/merge_panel.py
| def set_value(self, tolerance: float) -> None:
"""Set the tolerance (or the reach) as if it were typed.
`changed` is emitted, so the window finds the places again."""
self.tolerance.setValue(tolerance)
|
Functions: