def mergeResult(self, row: int, path: Sequence[Sequence[Tuple[float, float]]]): """Merge result function of dimensional synthesis.""" result = self.DimensionalSynthesis.mechanism_data(row) # exp_symbol = ['A', 'B', 'C', 'D', 'E'] exp_symbol = [] for exp in result['Link_expr'].split(';'): for name in str_between(exp, '[', ']').split(','): if name not in exp_symbol: exp_symbol.append(name) self.CommandStack.beginMacro( "Merge mechanism kit from {Dimensional Synthesis}") tmp_dict = {} for tag in sorted(exp_symbol): tmp_dict[tag] = self.addPoint( result[tag][0], result[tag][1], color=("Dark-Orange" if tag in result['Target'] else 'Green')) for i, exp in enumerate(result['Link_expr'].split(';')): self.addNormalLink( tuple(tmp_dict[name] for name in str_between(exp, '[', ']').split(','))) if i == 0: self.constrainLink(self.EntitiesLink.rowCount() - 1) self.CommandStack.endMacro() # Add the path. i = 0 while f"Algorithm_{i}" in self.InputsWidget.pathData(): i += 1 self.InputsWidget.addPath(f"Algorithm_{i}", path) self.MainCanvas.zoomToFit()
def __symbols(self) -> Set[str]: """Return all symbols.""" expr_list = set() for expr in self.expr_show.text().split(';'): param_list = str_between(expr, '[', ']').split(',') param_list.append(str_between(expr, '(', ')')) expr_list.update(param_list) return expr_list
def __init__( self, mechanism: Dict[str, Any], path: Sequence[Sequence[Tuple[float, float]]], parent: QWidget ): """Input link and path data.""" super(_DynamicCanvas, self).__init__(parent) self.mechanism = mechanism self.Path.path = path self.target_path = self.mechanism['Target'] self.__index = 0 self.__interval = 1 self.__path_count = max(len(path) for path in self.Path.path) - 1 self.pos: List[Tuple[float, float]] = [] # exp_symbol = {'P1', 'P2', 'P3', ...} exp_symbol = set() self.links = [] for exp in self.mechanism['Link_expr'].split(';'): names = str_between(exp, '[', ']').split(',') self.links.append(tuple(names)) for name in names: exp_symbol.add(name) self.exp_symbol = sorted(exp_symbol, key=lambda e: int(e.replace('P', ''))) # Error self.error = False self.__no_error = 0 # Timer start. self.__timer = QTimer(self) self.__timer.timeout.connect(self.__change_index) self.__timer.start(18)
def __load_data_base(self): """Show up the dialog to load structure data.""" dlg = CollectionsDialog(self.collections, self.getCollection, self) dlg.show() if not dlg.exec_(): return self.profile_name = dlg.name() params = dlg.params() # Add customize joints. graph = Graph(params['Graph']) self.setGraph(graph, params['pos']) self.PreviewWindow.cus = params['cus'] self.PreviewWindow.same = params['same'] # Grounded setting. drivers = set(params['Driver']) followers = set(params['Follower']) for row, link in enumerate(graph.nodes): points = {f'P{n}' for n, edge in edges_view(graph) if link in edge} if (drivers | followers) <= points: self.__set_ground(row) break # Driver, Follower, Target for expr in params['Expression'].split(';'): if str_before(expr, '[') != 'PLAP': continue base = str_between(expr, '[', ']').split(',')[0] self.__find_follower_to_remove(base) rotator = str_between(expr, '(', ')') self.driver_list.addItem(f"({base}, {rotator})") _set_warning(self.driver_label, not self.driver_list.count()) self.target_list.addItems(list(params['Target'])) _set_warning(self.target_label, not self.target_list.count() > 0) # Constraints self.constraint_list.addItems( [", ".join(c) for c in params['constraints']]) # Expression if params['Expression']: for expr in params['Expression'].split(';'): func = str_before(expr, '[') target = str_between(expr, '(', ')') params = str_between(expr, '[', ']').split(',') params.insert(0, func) params.append(target) self.__add_solution(*params) self.PreviewWindow.setStatus(target, True) _set_warning(self.expression_list_label, not self.PreviewWindow.isAllLock())
def __pop_expr(self): """Remove the last solution.""" count = self.expression_list.count() if not count: return expr = self.expression_list.item(count - 1).text() self.expression_list.takeItem(count - 1) self.PreviewWindow.setStatus(str_between(expr, '(', ')'), False) self.__set_parm_bind()
def outputTo(self, format_name: str, format_choose: List[str]) -> str: """Simple to support multiple format.""" file_name, suffix = QFileDialog.getSaveFileName( self, f"Save to {format_name}...", self.env + '/' + self.DatabaseWidget.file_name.baseName(), ';;'.join(format_choose)) if file_name: suffix = str_between(suffix, '(', ')').split('*')[-1] print(f"Format: {suffix}") if QFileInfo(file_name).completeSuffix() != suffix[1:]: file_name += suffix self.setLocate(QFileInfo(file_name).absolutePath()) return file_name
def __init__( self, mechanism: Dict[str, Any], path: Sequence[Sequence[Tuple[float, float]]], parent: QWidget ): """Show the information of results, and setup the preview canvas.""" super(PreviewDialog, self).__init__(parent) self.setupUi(self) self.setWindowTitle( f"Preview: {mechanism['Algorithm']} " f"(max {mechanism['last_gen']} generations)" ) self.setWindowFlags(self.windowFlags() | Qt.WindowMaximizeButtonHint) self.main_splitter.setSizes([800, 100]) self.splitter.setSizes([100, 100, 100]) preview_widget = _DynamicCanvas(mechanism, path, self) self.left_layout.insertWidget(0, preview_widget) # Basic information link_tags = [] for expr in mechanism['Expression'].split(';'): for p in str_between(expr, '[', ']').split(','): if ('L' in p) and (p not in link_tags): link_tags.append(p) self.basic_label.setText("\n".join([f"{tag}: {mechanism[tag]}" for tag in chain( ('Algorithm', 'time'), mechanism['Driver'], mechanism['Follower'], sorted(link_tags) )])) # Algorithm information if mechanism['interrupted'] == 'False': interrupt_icon = "task_completed.png" elif mechanism['interrupted'] == 'N/A': interrupt_icon = "question.png" else: interrupt_icon = "interrupted.png" text_list = [ f"Max generation: {mechanism['last_gen']}", f"<img src=\":/icons/{interrupt_icon}\" width=\"15\"/>" f"Interrupted at: {mechanism['interrupted']}" ] for k, v in mechanism['settings'].items(): text_list.append(f"{k}: {v}") text = "<br/>".join(text_list) self.algorithm_label.setText(f"<html><head/><body><p>{text}</p></body></html>") # Hardware information self.hardware_label.setText("\n".join([ f"{tag}: {mechanism['hardware_info'][tag]}" for tag in ('os', 'memory', 'cpu') ]))
def inputFrom(self, format_name: str, format_choose: List[str], multiple: bool = False) -> str: """Get file name(s).""" args = (f"Open {format_name} file{'s' if multiple else ''}...", self.env, ';;'.join(format_choose)) if multiple: file_name_s, suffix = QFileDialog.getOpenFileNames(self, *args) else: file_name_s, suffix = QFileDialog.getOpenFileName(self, *args) if file_name_s: suffix = str_between(suffix, '(', ')').split('*')[-1] print(f"Format: {suffix}") if type(file_name_s) == str: self.setLocate(QFileInfo(file_name_s).absolutePath()) else: self.setLocate(QFileInfo(file_name_s[0]).absolutePath()) return file_name_s
def from_profile(self, params: Dict[str, Any]): """Simple load by dict object.""" # Add customize joints. graph = Graph(params['Graph']) self.setGraph(graph, params['pos']) self.cus = params['cus'] self.same = params['same'] # Grounded setting. driver = set(params['Driver']) follower = set(params['Follower']) for row, link in enumerate(graph.nodes): points = set(f'P{n}' for n, edge in edges_view(graph) if link in edge) if (driver | follower) <= points: self.setGrounded(row) break # Expression if params['Expression']: for expr in params['Expression'].split(';'): self.setStatus(io.str_between(expr, '(', ')'), True) self.update()
def __has_solution(self, index: Optional[int] = None): """Set buttons enable if there has solution.""" if index is None: index = self.joint_name.currentIndex() if not index > -1: self.status_show.setText("N/A") self.PLAP_solution.setEnabled(False) self.PLLP_solution.setEnabled(False) return status = self.PreviewWindow.getStatus(index) if not status: status_str = "Not known." elif index in self.PreviewWindow.same: status_str = f"Same as P{self.PreviewWindow.same[index]}." else: status_str = "Grounded." for expr in list_texts(self.expression_list): if index == int(str_between(expr, '(', ')').replace('P', '')): status_str = f"From {str_before(expr, '[')}." self.status_show.setText(status_str) self.PLAP_solution.setEnabled(not status) self.PLLP_solution.setEnabled(not status)
def paintEvent(self, event): """Draw the structure.""" width = self.width() height = self.height() if self.pos: x_right, x_left, y_top, y_bottom = self.__zoom_to_fit_limit() x_diff = x_left - x_right y_diff = y_top - y_bottom x_diff = x_diff if x_diff else 1 y_diff = y_diff if y_diff else 1 if width / x_diff < height / y_diff: factor = width / x_diff else: factor = height / y_diff self.zoom = factor * 0.95 self.ox = width / 2 - (x_left + x_right) / 2 * self.zoom self.oy = height / 2 + (y_top + y_bottom) / 2 * self.zoom else: sq_w = 240 self.zoom = (width / sq_w) if (width <= height) else (height / sq_w) self.ox = width / 2 self.oy = height / 2 super(PreviewCanvas, self).paintEvent(event) pen = QPen() pen.setWidth(self.joint_size) self.painter.setPen(pen) self.painter.setBrush(QBrush(QColor(226, 219, 190, 150))) # Links for link in self.G.nodes: if link == self.grounded: continue points = [] # Points that is belong with the link. for num, edge in edges_view(self.G): if link in edge: if num in self.same: num = self.same[num] x, y = self.pos[num] points.append((x * self.zoom, y * -self.zoom)) # Customize points. for name, link_ in self.cus.items(): if link == link_: x, y = self.pos[int(name.replace('P', ''))] points.append((x * self.zoom, y * -self.zoom)) self.painter.drawPolygon(*convex_hull(points, as_qpoint=True)) # Nodes for node, (x, y) in self.pos.items(): if node in self.same: continue x *= self.zoom y *= -self.zoom if node in (self.Driver, self.Target): if node == self.Driver: pen.setColor(color_qt('Red')) elif node == self.Target: pen.setColor(color_qt('Yellow')) self.painter.setPen(pen) self.painter.drawEllipse(QPointF(x, y), self.joint_size, self.joint_size) if self.getStatus(node): color = color_qt('Dark-Magenta') else: color = color_qt('Green') pen.setColor(color) self.painter.setPen(pen) self.painter.setBrush(QBrush(color)) self.painter.drawEllipse(QPointF(x, y), self.joint_size, self.joint_size) pen.setColor(color_qt('Black')) self.painter.setPen(pen) # Solutions if self.showSolutions: solutions = self.get_solutions() if solutions: for expr in solutions.split(';'): self.drawSolution( io.str_before(expr, '['), io.str_between(expr, '[', ']').split(','), io.str_between(expr, '(', ')'), self.pos ) # Text of node. pen.setColor(Qt.black) self.painter.setPen(pen) for node, (x, y) in self.pos.items(): if node in self.same: continue x *= self.zoom x += 2 * self.joint_size y *= -self.zoom y -= 2 * self.joint_size self.painter.drawText(QPointF(x, y), f'P{node}') self.painter.end()