class OrderShortestPath(OrderHandler): """ This uses Dijkstra's algorithm to find the shortest path. """ name = QApplication.translate("job", "Shortest Path") time_limit = 0.2 # This is in the UI thread def order(self, job, path): """ Sort subpaths by minimizing the distances between all start and end points. """ subpaths = split_painter_path(path) log.debug("Subpath count: {}".format(len(subpaths))) # Cache all start and end points time_limit = time() + self.time_limit zero = QVector2D(0, 0) for sp in subpaths: # Average start and end into one "vertex" start = sp.elementAt(0) end = sp.elementAt(sp.elementCount() - 1) sp.start_point = QVector2D(start.x, start.y) sp.end_point = QVector2D(end.x, end.y) distance = QVector2D.distanceToPoint original = subpaths[:] result = [] p = zero while subpaths: best = sys.maxsize shortest = None for sp in subpaths: d = distance(p, sp.start_point) if d < best: best = d shortest = sp p = shortest.end_point result.append(shortest) subpaths.remove(shortest) # time.time() is slow so limit the calls if time() > time_limit: result.extend(subpaths) # At least part of it is optimized log.debug("Shortest path search aborted (time limit reached)") break d = self.subpath_move_distance(zero, original) d = d - self.subpath_move_distance(zero, result) log.debug("Shortest path search: Saved {} in of movement ".format( to_unit(d, 'in'))) return join_painter_paths(result) def subpath_move_distance(self, p, subpaths, limit=sys.maxsize): # Collect start and end points d = 0 # Local ref saves a lookup per iter distance = QVector2D.distanceToPoint for sp in subpaths: d += distance(p, sp.start_point) if d > limit: break # Over the limit already abort p = sp.end_point return d
class OrderReversed(OrderHandler): name = QApplication.translate("job", "Reversed") def order(self, job, path): return path.toReversed()
class OrderMaxY(OrderHandler): name = QApplication.translate("job", 'Max Y') def order(self, job, path): return self.order_by_func(job, path, lambda p: p.boundingRect().top())
class OrderNormal(OrderHandler): name = QApplication.translate("job", "Normal") def order(self, job, path): return path
def tr(*args, **kwargs): """ Alias to translate """ from enaml.qt.QtWidgets import QApplication return QApplication.translate(*args, **kwargs)