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 add_continuity_correction(self, offset_path, blade_path, point): """ Adds if the upcoming angle and previous angle are not the same we need to correct for that difference by "arcing back" about the current blade point with a radius equal to the offset. """ # Current blade position cur = blade_path.currentPosition() # Determine direction of next move sp = QPainterPath() sp.moveTo(cur) sp.lineTo(point) next_angle = sp.angleAtPercent(1) # Direction of last move angle = blade_path.angleAtPercent(1) # If not continuous it needs corrected with an arc if isnan(angle) or isnan(next_angle): return if abs(angle - next_angle) > self.config.cutoff: r = self.config.offset a = radians(next_angle) dx, dy = r*cos(a), -r*sin(a) po = QPointF(cur.x()+dx, cur.y()+dy) c = offset_path.currentPosition() dx, dy = po.x()-cur.x()+c.x()-cur.x(), po.y()-cur.y()+c.y()-cur.y() c1 = QPointF(cur.x()+dx, cur.y()+dy) offset_path.quadTo(c1, po)