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 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)