示例#1
0
    def from_profile(self, params: Dict[str, Any]) -> None:
        """Simple load by dict object."""
        # Customize points and multiple joints
        g = Graph(params['graph'])
        expression: str = params['expression']
        pos_list = parse_pos(expression)
        cus: Dict[int, int] = params['cus']
        same: Dict[int, int] = params['same']
        self.cus = cus
        self.same = same
        for node, ref in sorted(self.same.items()):
            pos_list.insert(node, pos_list[ref])
        self.set_graph(g, {i: (x, y) for i, (x, y) in enumerate(pos_list)})

        # Grounded setting
        for row in self.grounded_detect(set(params['placement']), g,
                                        self.same):
            self.set_grounded(row)

        # Driver setting
        input_list: List[Tuple[Tuple[int, int],
                               Tuple[float, float]]] = params['input']
        self.driver.clear()
        self.driver.update(b for (b, _), _ in input_list)

        # Target setting
        target: Dict[int, Sequence[_Coord]] = params['target']
        self.target.clear()
        self.target.update(target)

        self.update()
 def __from_profile(self) -> None:
     """Show up the dialog to load structure data."""
     dlg = CollectionsDialog(
         self.collections,
         self.get_configure,
         self.project_no_save,
         self.prefer.tick_mark_option,
         self.configure_canvas.monochrome,
         self
     )
     dlg.show()
     if not dlg.exec_():
         dlg.deleteLater()
         return
     # Add customize joints
     params = dlg.params
     graph = Graph(params['graph'])
     expression: str = params['expression']
     pos_list = parse_pos(expression)
     cus: Dict[int, int] = params['cus']
     same: Dict[int, int] = params['same']
     for node, ref in sorted(same.items()):
         pos_list.insert(node, pos_list[ref])
     if not self.set_graph(graph, {i: (x, y) for i, (x, y) in enumerate(pos_list)}):
         dlg.deleteLater()
         return
     self.profile_name.setText(dlg.name)
     dlg.deleteLater()
     del dlg
     self.configure_canvas.cus = cus
     self.configure_canvas.same = same
     # Grounded setting
     for row in PreviewCanvas.grounded_detect(set(params['placement']), graph, same):
         self.__set_grounded(row)
     # Driver, Target
     input_list: List[Tuple[Tuple[int, int], Tuple[float, float]]] = params['input']
     self.driver_list.addItems(f"(P{b}, P{d})" for (b, d), _ in input_list)
     self.configure_canvas.set_driver([d for d, _ in input_list])
     _set_warning(self.driver_label, self.driver_list.count() == 0)
     target_list: Dict[int, Sequence[_Coord]] = params['target']
     self.configure_canvas.set_target(sorted(target_list))
     self.target_list.addItems(f"P{n}" for n in target_list)
     _set_warning(self.target_label, self.target_list.count() == 0)
     # Expression
     self.expr_show.setText(params['expression'])
示例#3
0
    def __set_profile(self, profile_name: str, params: Dict[str, Any]) -> None:
        """Set profile to sub-widgets."""
        self.__clear_settings()
        self.mech = deepcopy(params)
        expression: str = self.mech['expression']
        self.expression_string.setText(expression)
        target: Dict[int, List[_Coord]] = self.mech['target']
        for p in sorted(target):
            self.target_points.addItem(f"P{p}")
            if target[p]:
                self.path[p] = target[p].copy()
            else:
                self.path[p] = []
        if self.has_target():
            self.target_points.setCurrentRow(0)
        self.target_label.setVisible(self.has_target())
        inputs: List[Tuple[_Pair, List[float]]] = self.mech.get('input', [])
        self.mech['input'] = inputs
        placement: Dict[int, Optional[_Range]] = self.mech.get('placement', {})
        self.mech['placement'] = placement
        # Table settings
        self.parameter_list.setRowCount(0)
        self.parameter_list.setRowCount(len(inputs) + len(placement) + 1)
        row = 0

        def spinbox(
            v: float = 0.,
            *,
            minimum: float = 0.,
            maximum: float = 9999.,
            prefix: bool = False
        ) -> QDoubleSpinBox:
            double_spinbox = QDoubleSpinBox()
            double_spinbox.setMinimum(minimum)
            double_spinbox.setMaximum(maximum)
            double_spinbox.setValue(v)
            if prefix:
                double_spinbox.setPrefix("±")
            return double_spinbox

        def set_angle(index1: int, index2: int) -> Callable[[float], None]:
            """Return a slot function use to set angle value."""
            @Slot(float)
            def func(value: float) -> None:
                inputs[index1][1][index2] = value
            return func

        # Angles
        for i, ((b, d), se) in enumerate(inputs):
            self.parameter_list.setItem(row, 0, QTableWidgetItem(f"P{b}->P{d}"))
            self.parameter_list.setItem(row, 1, QTableWidgetItem('input'))
            s1 = spinbox(se[0], maximum=360.)
            s2 = spinbox(se[1], maximum=360.)
            self.parameter_list.setCellWidget(row, 2, s1)
            self.parameter_list.setCellWidget(row, 3, s2)
            s1.valueChanged.connect(set_angle(i, 0))
            s2.valueChanged.connect(set_angle(i, 1))
            row += 1

        # Grounded joints
        self.preview_canvas.from_profile(self.mech)
        pos_list = parse_pos(expression)
        for node, ref in sorted(self.preview_canvas.same.items()):
            pos_list.insert(node, pos_list[ref])
        for p in sorted(placement):
            coord = placement[p]
            self.parameter_list.setItem(row, 0, QTableWidgetItem(f"P{p}"))
            self.parameter_list.setItem(row, 1, QTableWidgetItem('placement'))
            x, y = self.preview_canvas.pos[p]
            for i, s in enumerate([
                spinbox(coord[0] if coord else x, minimum=-9999.),
                spinbox(coord[1] if coord else y, minimum=-9999.),
                spinbox(coord[2] if coord else 5., prefix=True),
            ]):
                s.valueChanged.connect(self.update_range)
                self.parameter_list.setCellWidget(row, i + 2, s)
            row += 1
        # Default value of upper and lower
        self.mech['upper'] = self.mech.get('upper', 100)
        self.mech['lower'] = self.mech.get('lower', 0)

        def set_link(opt: str) -> Callable[[float], None]:
            """Set link length."""
            @Slot(float)
            def func(value: float) -> None:
                self.mech[opt] = value
            return func

        self.parameter_list.setItem(row, 0, QTableWidgetItem("L"))
        self.parameter_list.setItem(row, 1, QTableWidgetItem('link'))
        for i, (s, tag) in enumerate([(spinbox(), 'upper'), (spinbox(), 'lower')]):
            s.setValue(self.mech[tag])
            s.valueChanged.connect(set_link(tag))
            self.parameter_list.setCellWidget(row, i + 2, s)
        # Update previews
        self.update_range()
        self.profile_name.setText(profile_name)
        # Default value of algorithm option
        if 'settings' in self.mech:
            self.alg_options.update(self.mech['settings'])
        else:
            self.__set_algorithm_default()
        self.__able_to_generate()
示例#4
0
    def __set_profile(self, profile_name: str, params: Dict[str, Any]) -> None:
        """Set profile to sub-widgets."""
        self.__clear_settings()
        self.mech_params = deepcopy(params)
        expression: str = self.mech_params['Expression']
        self.expression_string.setText(expression)
        target: Dict[int, List[_Coord]] = self.mech_params['Target']
        for name in sorted(target):
            self.target_points.addItem(f"P{name}")
            path = target[name]
            if path:
                self.path[name] = path.copy()
            else:
                self.path[name] = []
        if self.has_target():
            self.target_points.setCurrentRow(0)
        self.target_label.setVisible(self.has_target())

        # Parameter of link length and input angle.
        link_list = set()
        for vlink in parse_vlinks(expression):
            if len(vlink.points) < 2 or vlink.name == "ground":
                continue
            a = vlink.points[0]
            b = vlink.points[1]
            link_list.add(f"P{a}<->P{b}")
            for c in vlink.points[2:]:
                for d in (a, b):
                    link_list.add(f"P{c}<->P{d}")
        link_count = len(link_list)

        angle_list = set()
        input_list: List[Tuple[int, int]] = self.mech_params['input']
        for b, d in input_list:
            angle_list.add(f"P{b}->P{d}")
        angle_count = len(angle_list)

        self.parameter_list.setRowCount(0)
        placement: Dict[int, Tuple[float, float,
                                   float]] = self.mech_params['Placement']
        self.parameter_list.setRowCount(
            len(placement) + link_count + angle_count)

        def spinbox(v: float,
                    *,
                    minimum: float = 0.,
                    maximum: float = 9999.,
                    prefix: bool = False) -> QDoubleSpinBox:
            double_spinbox = QDoubleSpinBox()
            double_spinbox.setMinimum(minimum)
            double_spinbox.setMaximum(maximum)
            double_spinbox.setSingleStep(10.0)
            double_spinbox.setValue(v)
            if prefix:
                double_spinbox.setPrefix("±")
            return double_spinbox

        # Position
        self.preview_canvas.from_profile(self.mech_params)
        pos_list = parse_pos(expression)
        for node, ref in sorted(self.preview_canvas.same.items()):
            pos_list.insert(node, pos_list[ref])

        row = 0
        for name in sorted(placement):
            coord = placement[name]
            self.parameter_list.setItem(row, 0, QTableWidgetItem(f"P{name}"))
            self.parameter_list.setItem(row, 1, QTableWidgetItem('Placement'))
            x, y = self.preview_canvas.pos[name]
            for i, s in enumerate([
                    spinbox(coord[0] if coord else x, minimum=-9999.),
                    spinbox(coord[1] if coord else y, minimum=-9999.),
                    spinbox(coord[2] if coord else 25., prefix=True),
            ]):
                s.valueChanged.connect(self.update_range)
                self.parameter_list.setCellWidget(row, i + 2, s)
            row += 1

        # Default value of upper and lower
        for name in ('upper', 'lower'):
            if name not in self.mech_params:
                self.mech_params[name] = [0.] * (link_count + angle_count)

        upper_list: List[float] = self.mech_params['upper']
        lower_list: List[float] = self.mech_params['lower']

        def set_by_center(
                index: int,
                get_range: Callable[[], float]) -> Callable[[float], None]:
            """Return a slot function use to set limit value by center."""
            @Slot(float)
            def func(value: float) -> None:
                range_value = get_range()
                upper_list[index] = value + range_value
                lower_list[index] = value - range_value

            return func

        def set_by_range(
                index: int,
                get_value: Callable[[], float]) -> Callable[[float], None]:
            """Return a slot function use to set limit value by range."""
            @Slot(float)
            def func(value: float) -> None:
                center = get_value()
                upper_list[index] = center + value
                lower_list[index] = center - value

            return func

        for i, name in enumerate(sorted(link_list) + sorted(angle_list)):
            name_item = QTableWidgetItem(name)
            name_item.setToolTip(name)
            self.parameter_list.setItem(row, 0, name_item)
            upper = upper_list[i]
            lower = lower_list[i]
            if name in link_list:
                type_name = "Link"
                n1, n2 = (int(n.replace('P', '')) for n in name.split('<->'))
                link_length = self.preview_canvas.distance(n1, n2)
                if upper == 0.:
                    upper = link_length + 50
                if lower <= 0.:
                    lower = link_length - 50
                    lower = 0. if lower < 0 else lower
            else:
                type_name = "Input"
                if upper == 0.:
                    upper = 360.
            self.parameter_list.setItem(row, 1, QTableWidgetItem(type_name))
            # Set values
            upper_list[i] = upper
            lower_list[i] = lower
            # Spin box
            error_range = (upper - lower) / 2
            default_value = error_range + lower
            if name in link_list:
                s1 = spinbox(default_value)
            else:
                s1 = spinbox(default_value, maximum=360.)
            self.parameter_list.setCellWidget(row, 2, s1)
            s2 = spinbox(error_range, prefix=True)
            self.parameter_list.setCellWidget(row, 4, s2)
            # Signals
            s1.valueChanged.connect(set_by_center(i, s2.value))
            s2.valueChanged.connect(set_by_range(i, s1.value))
            row += 1

        self.update_range()

        self.profile_name.setText(profile_name)

        # Default value of algorithm option.
        if 'settings' in self.mech_params:
            self.alg_options.update(self.mech_params['settings'])
        else:
            self.__set_algorithm_default()

        self.__able_to_generate()
示例#5
0
    def __set_profile(self, profile_name: str, params: Dict[str, Any]) -> None:
        """Set profile to sub-widgets."""
        self.__clear_settings()
        self.mech = deepcopy(params)
        expression: str = self.mech['expression']
        self.expression_string.setText(expression)
        target: Dict[int, List[_Coord]] = self.mech['target']
        for p in sorted(target):
            self.target_points.addItem(f"P{p}")
            if target[p]:
                self.path[p] = target[p].copy()
            else:
                self.path[p] = []
        if self.has_target():
            self.target_points.setCurrentRow(0)
        self.target_label.setVisible(self.has_target())
        # Parameter of link length and input angle.
        link_list = []
        for vlink in parse_vlinks(expression):
            if len(vlink.points) < 2 or vlink.name == VLink.FRAME:
                continue
            a = vlink.points[0]
            b = vlink.points[1]
            link_list.append((a, b))
            for c in vlink.points[2:]:
                for d in (a, b):
                    link_list.append((c, d))
        link_count = len(link_list)
        inputs: List[Tuple[Tuple[int, int], List[float]]] = self.mech['input']
        self.parameter_list.setRowCount(0)
        placement: Dict[int, Optional[Tuple[float, float,
                                            float]]] = self.mech['placement']
        # Table settings
        self.parameter_list.setRowCount(
            len(inputs) + len(placement) + link_count)
        row = 0

        def spinbox(v: float,
                    *,
                    minimum: float = 0.,
                    maximum: float = 9999.,
                    prefix: bool = False) -> QDoubleSpinBox:
            double_spinbox = QDoubleSpinBox()
            double_spinbox.setMinimum(minimum)
            double_spinbox.setMaximum(maximum)
            double_spinbox.setValue(v)
            if prefix:
                double_spinbox.setPrefix("±")
            return double_spinbox

        def set_angle(index1: int, index2: int) -> Callable[[float], None]:
            """Return a slot function use to set angle value."""
            @Slot(float)
            def func(value: float) -> None:
                inputs[index1][1][index2] = value

            return func

        # Angles
        for i, ((b, d), se) in enumerate(inputs):
            self.parameter_list.setItem(row, 0,
                                        QTableWidgetItem(f"P{b}->P{d}"))
            self.parameter_list.setItem(row, 1, QTableWidgetItem('input'))
            s1 = spinbox(se[0], maximum=360.)
            s2 = spinbox(se[1], maximum=360.)
            self.parameter_list.setCellWidget(row, 2, s1)
            self.parameter_list.setCellWidget(row, 3, s2)
            s1.valueChanged.connect(set_angle(i, 0))
            s2.valueChanged.connect(set_angle(i, 1))
            row += 1

        # Grounded joints
        self.preview_canvas.from_profile(self.mech)
        pos_list = parse_pos(expression)
        for node, ref in sorted(self.preview_canvas.same.items()):
            pos_list.insert(node, pos_list[ref])
        for p in sorted(placement):
            coord = placement[p]
            self.parameter_list.setItem(row, 0, QTableWidgetItem(f"P{p}"))
            self.parameter_list.setItem(row, 1, QTableWidgetItem('placement'))
            x, y = self.preview_canvas.pos[p]
            for i, s in enumerate([
                    spinbox(coord[0] if coord else x, minimum=-9999.),
                    spinbox(coord[1] if coord else y, minimum=-9999.),
                    spinbox(coord[2] if coord else 25., prefix=True),
            ]):
                s.valueChanged.connect(self.update_range)
                self.parameter_list.setCellWidget(row, i + 2, s)
            row += 1
        # Default value of upper and lower
        upper_list: List[float] = self.mech.get('upper', [0.] * link_count)
        lower_list: List[float] = self.mech.get('lower', [0.] * link_count)
        self.mech['upper'] = upper_list
        self.mech['lower'] = lower_list

        def set_by_center(
                index: int,
                get_range: Callable[[], float]) -> Callable[[float], None]:
            """Return a slot function use to set limit value by center."""
            @Slot(float)
            def func(value: float) -> None:
                range_value = get_range()
                upper_list[index] = value + range_value
                lower_list[index] = value - range_value

            return func

        def set_by_range(
                index: int,
                get_value: Callable[[], float]) -> Callable[[float], None]:
            """Return a slot function use to set limit value by range."""
            @Slot(float)
            def func(value: float) -> None:
                center = get_value()
                upper_list[index] = center + value
                lower_list[index] = center - value

            return func

        # Links
        for i, (a, b) in enumerate(sorted(link_list)):
            self.parameter_list.setItem(row, 0,
                                        QTableWidgetItem(f"P{a}<->P{b}"))
            link_length = self.preview_canvas.distance(a, b)
            self.parameter_list.setItem(row, 1, QTableWidgetItem('link'))
            # Set values
            if upper_list[i] == 0.:
                upper_list[i] = link_length + 50
            if lower_list[i] <= 0.:
                lower_list[i] = link_length - 50
                lower_list[i] = 0. if lower_list[i] < 0 else lower_list[i]
            # Spinbox
            error_range = (upper_list[i] - lower_list[i]) / 2
            s1 = spinbox(error_range + lower_list[i])
            s2 = spinbox(error_range, prefix=True)
            self.parameter_list.setCellWidget(row, 2, s1)
            self.parameter_list.setCellWidget(row, 4, s2)
            s1.valueChanged.connect(set_by_center(i, s2.value))
            s2.valueChanged.connect(set_by_range(i, s1.value))
            row += 1
        self.update_range()
        self.profile_name.setText(profile_name)
        # Default value of algorithm option.
        if 'settings' in self.mech:
            self.alg_options.update(self.mech['settings'])
        else:
            self.__set_algorithm_default()
        self.__able_to_generate()