def __init__(self, mechanism: Dict[str, Any], path: Sequence[Sequence[_Coord]], vpoints: List[VPoint] = None, vlinks: List[VLink] = None, parent: QWidget = None): """Input link and path data.""" super(_DynamicCanvas, self).__init__(parent) self.mechanism = mechanism self.vpoints = vpoints or [] self.vlinks = vlinks or [] self.no_mechanism = not self.vpoints or not self.vlinks use_norm = self.no_mechanism and self.mechanism.get( 'shape_only', False) # Target path same: Dict[int, int] = self.mechanism['same'] target_path: _TargetPath = self.mechanism['target'] for i, p in target_path.items(): for j in range(i): if j in same: i -= 1 if use_norm: self.target_path[i] = [(x, y) for x, y in norm_path(p)] else: self.target_path[i] = p self.path.path = [] for i, p in enumerate(path): if i in self.target_path and use_norm: self.path.path.append([(x, y) for x, y in norm_path(efd_fitting(p))]) else: self.path.path.append(p) self.__index = 0 self.__interval = 1 self.__path_count = max(len(path) for path in self.path.path) - 1 self.pos = [] # Error self.error = False self.__no_error = 0 if self.no_mechanism: return # Ranges ranges: Dict[int, _Range] = self.mechanism['placement'] self.ranges.update({ f"P{i}": QRectF(QPointF(values[0] - values[2], values[1] + values[2]), QSizeF(values[2] * 2, values[2] * 2)) for i, values in ranges.items() }) # Timer self.__timer = QTimer() self.__timer.timeout.connect(self.__change_index) self.__timer.start(18)
def __efd_path(self) -> None: """Elliptical Fourier Descriptors.""" path = self.current_path() n, ok = QInputDialog.getInt(self, "Elliptical Fourier Descriptors", "The number of points:", len(path), 3) if not ok: return dlg = QProgressDialog("Path transform.", "Cancel", 0, 1, self) dlg.setWindowTitle("Elliptical Fourier Descriptors") dlg.show() self.set_path(efd_fitting(path, n)) dlg.setValue(1) dlg.deleteLater()
def __gen_fitting(self) -> ndarray: """Generate the fitted curve.""" num = self.num_points.value() is_close = self.close_path_option.isChecked() if is_close: num += 1 if self.bspline_option.isChecked(): if is_close: path = concatenate((self.path, self.path[:1, :])) else: path = self.path tck = splprep((path[:, 0], path[:, 1]), per=is_close) path = array(splev(linspace(0, 1, num, endpoint=True), tck[0])).T else: path = efd_fitting(self.path, num) if is_close: path = path[:-1] return path
def test_fitting(self): ans = efd_fitting(PATH, 20) self.assertTrue(isclose(ans, TARGET).all())