def process_cubic(self, offset_path, blade_path, params, quality): """ Add offset correction to a cubic bezier. """ r = self.config.offset p0 = blade_path.currentPosition() p1, p2, p3 = params self.add_continuity_correction(offset_path, blade_path, p1) curve = QPainterPath() curve.moveTo(p0) curve.cubicTo(*params) p = QPainterPath() p.moveTo(p0) if quality == 1: polygon = curve.toSubpathPolygons(IDENITY_MATRIX)[0] else: m = QTransform.fromScale(quality, quality) m_inv = QTransform.fromScale(1/quality, 1/quality) polygon = m_inv.map(curve.toSubpathPolygons(m)[0]) for point in polygon: p.lineTo(point) t = curve.percentAtLength(p.length()) angle = curve.angleAtPercent(t) a = radians(angle) dx, dy = r*cos(a), -r*sin(a) offset_path.lineTo(point.x()+dx, point.y()+dy) blade_path.cubicTo(*params)
def apply_blade_offset(self, poly, offset): """ Apply blade offset to the given polygon by appending a quadratic bezier to each point . """ # Use a QPainterPath to track the distance in c++ path = QPainterPath() cutoff = cos(radians(self.config.cutoff)) # Forget last = None n = len(poly) for i, p in enumerate(poly): if i == 0: path.moveTo(p) last_path = QPainterPath() last_path.moveTo(p) last = p continue # Move to the point path.lineTo(p) if i+1 == n: # Done break # Get next point next = poly.at(i+1) # Make our paths last_path.lineTo(p) next_path = QPainterPath() next_path.moveTo(p) next_path.lineTo(next) # Get angle between the two components u, v = QVector2D(last-p), QVector2D(next-p) cos_theta = QVector2D.dotProduct(u.normalized(), v.normalized()) # If the angle is large enough to need compensation if (cos_theta < cutoff and last_path.length() > offset and next_path.length() > offset): # Calculate the extended point t = last_path.percentAtLength(offset) c1 = p+(last_path.pointAtPercent(t)-last) c2 = p t = next_path.percentAtLength(offset) ep = next_path.pointAtPercent(t) if offset > 2: # Can smooth it for larger offsets path.cubicTo(c1, c2, ep) else: # This works for small offsets < 0.5 mm path.lineTo(c1) path.lineTo(ep) # Update last last_path = next_path last = p return path.toSubpathPolygons(IDENITY_MATRIX)
def splitAtPercent(self, t): paths = [] path = QPainterPath() i = 0 while i < self.elementCount(): e = self.elementAt(i) if e.type == ElementType.MoveToElement: if not path.isEmpty(): paths.append(path) path = QPainterPath(QPointF(e.x, e.y)) elif e.type == ElementType.LineToElement: path.lineTo(QPointF(e.x, e.y)) elif e.type == ElementType.CurveToElement: e1, e2 = self.elementAt(i + 1), self.elementAt(i + 2) path.cubicTo(QPointF(e.x, e.y), QPointF(e1.x, e1.y), QPointF(e2.x, e2.y)) i += 2 else: raise ValueError("Invalid element type %s" % (e.type, )) i += 1 if not path.isEmpty(): paths.append(path) return paths
def request_relayout(self): # y = 0.0 # for child in self.children(): # if not isinstance(child, QtContainer): # continue # scene_proxy = self._proxies[child] # width, height = child._layout_manager.best_size() # scene_proxy.setPos(0.0, y) # y += height + 25.0 for p in self._edge_paths: self.scene.removeItem(p) self._edge_paths = [] g = pygraphviz.AGraph(directed=True) g.graph_attr['nodesep'] = 100 g.graph_attr['ranksep'] = 50 g.node_attr['shape'] = 'rect' children_names = {child.declaration.name for child in self.children() if isinstance(child, QtContainer)} if any(from_ not in children_names or to not in children_names for (from_, to) in self.declaration.edges): # hasn't finished being set up yet return for child in self.children(): if not isinstance(child, QtContainer): continue scene_proxy = self._proxy(child) width, height = child._layout_manager.best_size() scene_proxy.setGeometry(QRectF(0.0, 0.0, width, height)) g.add_node(child.declaration.name, width=width, height=height) for from_, to in self.declaration.edges: g.add_edge(from_, to) g.layout(prog='dot') for child in self.children(): if not isinstance(child, QtContainer): continue scene_proxy = self._proxies[child] node = g.get_node(child.declaration.name) center_x, center_y = (-float(v)/72.0 for v in node.attr['pos'].split(',')) width, height = child._layout_manager.best_size() x = center_x - (width / 2.0) y = center_y - (height / 2.0) scene_proxy.setPos(x, y) for from_, to in self.declaration.edges: if from_ not in children_names or to not in children_names: continue edge = g.get_edge(from_, to) # TODO: look at below code all_points = [tuple(-float(v)/72.0 for v in t.strip('e,').split(',')) for t in edge.attr['pos'].split(' ')] arrow = all_points[0] start_point = all_points[1] painter = QPainterPath(QPointF(*start_point)) for c1, c2, end in grouper(all_points[2:], 3): painter.cubicTo(QPointF(*c1), QPointF(*c2), QPointF(*end)) self._edge_paths.append(self.scene.addPath(painter)) rect = self.scene.itemsBoundingRect() # Enlarge the rect so there is enough room at right and bottom rect.setX(rect.x() - self.LEFT_PADDING) rect.setY(rect.y() - self.TOP_PADDING) rect.setWidth(rect.width() + 2 * self.LEFT_PADDING) rect.setHeight(rect.height() + 2 * self.TOP_PADDING) self.scene.setSceneRect(rect) self.widget.viewport().update() self.show_selected()
def request_relayout(self): # y = 0.0 # for child in self.children(): # if not isinstance(child, QtContainer): # continue # scene_proxy = self._proxies[child] # width, height = child._layout_manager.best_size() # scene_proxy.setPos(0.0, y) # y += height + 25.0 for p in self._edge_paths: self.scene.removeItem(p) self._edge_paths = [] g = pygraphviz.AGraph(directed=True) g.graph_attr['nodesep'] = 100 g.graph_attr['ranksep'] = 50 g.node_attr['shape'] = 'rect' children_names = {child.declaration.name for child in self.children() if isinstance(child, QtContainer)} if any(from_ not in children_names or to not in children_names for (from_, to) in self.declaration.edges): # hasn't finished being set up yet return for child in self.children(): if not isinstance(child, QtContainer): continue scene_proxy = self._proxy(child) width, height = child._layout_manager.best_size() scene_proxy.setGeometry(QRectF(0.0, 0.0, width, height)) g.add_node(child.declaration.name, width=width, height=height) for from_, to in self.declaration.edges: g.add_edge(from_, to) before = time.time() g.layout(prog='dot') after = time.time() for child in self.children(): if not isinstance(child, QtContainer): continue scene_proxy = self._proxies[child] node = g.get_node(child.declaration.name) center_x, center_y = (-float(v)/72.0 for v in node.attr['pos'].split(',')) width, height = child._layout_manager.best_size() x = center_x - (width / 2.0) y = center_y - (height / 2.0) scene_proxy.setPos(x, y) for from_, to in self.declaration.edges: if from_ not in children_names or to not in children_names: continue edge = g.get_edge(from_, to) # TODO: look at below code all_points = [tuple(-float(v)/72.0 for v in t.strip('e,').split(',')) for t in edge.attr['pos'].split(' ')] arrow = all_points[0] start_point = all_points[1] painter = QPainterPath(QPointF(*start_point)) for c1, c2, end in grouper(all_points[2:], 3): painter.cubicTo(QPointF(*c1), QPointF(*c2), QPointF(*end)) self._edge_paths.append(self.scene.addPath(painter)) self.show_selected()