def parse(self, e): c = QtCore.QPointF(*map(self.parseUnit, (e.attrib.get('cx', 0), e.attrib.get('cy', 0)))) rx, ry = map(self.parseUnit, (e.attrib.get('rx', 0), e.attrib.get('ry', 0))) self.addEllipse(c, rx, ry)
def _job_changed(self, change): """ Recreate an instance of of the plot using the current settings """ if self._blocked: return if change['name'] == 'copies': self._desired_copies = self.copies #try: model = QtGui.QPainterPath() if not self.path: return path = self._create_copy() # Update size bbox = path.boundingRect() self.size = [bbox.width(), bbox.height()] # Create copies c = 0 points = self._copy_positions_iter(path) if self.auto_copies: self.stack_size = self._compute_stack_sizes(path) if self.stack_size[0]: copies_left = self.copies % self.stack_size[0] if copies_left: # not a full stack with self.events_suppressed(): self.copies = self._desired_copies self.add_stack() while c < self.copies: x, y = next(points) model.addPath(path * QtGui.QTransform.fromTranslate(x, -y)) c += 1 # Create weedline if self.plot_weedline: self._add_weedline(model, self.plot_weedline_padding) # Move to 0,0 bbox = model.boundingRect() p = bbox.bottomLeft() tx, ty = -p.x(), -p.y() # Center or set to padding tx += ((self.material.width() - bbox.width()) / 2.0 if self.align_center[0] else self.material.padding_left) ty += (-(self.material.height() - bbox.height()) / 2.0 if self.align_center[1] else -self.material.padding_bottom) t = QtGui.QTransform.fromTranslate(tx, ty) model = model * t end_point = (QtCore.QPointF( 0, -self.feed_after + model.boundingRect().top()) if self.feed_to_end else QtCore.QPointF(0, 0)) model.moveTo(end_point) # Set new model self.model = model #.simplified()
def process(self, model): """ Process the path model of a job and return each command within the job. Parameters ---------- model: QPainterPath The path to process Returns ------- generator: A list or generator object that yields each command to invoke on the device and the distance moved. In the format (distance, cmd, args, kwargs) """ config = self.config # Previous point _p = QtCore.QPointF(self.origin[0], self.origin[1]) # Do a final translation since Qt's y axis is reversed from svg's # It should now be a bbox of (x=0, y=0, width, height) # this creates a copy model = model * QtGui.QTransform.fromScale(1, -1) # Determine if interpolation should be used skip_interpolation = (self.connection.always_spools or config.spooled or not config.interpolate) # speed = distance/seconds # So distance/speed = seconds to wait step_size = config.step_size if not skip_interpolation and step_size <= 0: raise ValueError("Cannot have a step size <= 0!") try: # Apply device filters for f in self.filters: log.debug(" filter | Running {} on model".format(f)) model = f.apply_to_model(model, job=self) # Since Qt's toSubpathPolygons converts curves without accepting # a parameter to set the minimum distance between points on the # curve, we need to prescale by a "quality factor" before # converting then undo the scaling to effectively adjust the # number of points on a curve. m = QtGui.QTransform.fromScale( config.quality_factor, config.quality_factor) # Some versions of Qt seem to require a value in toSubpathPolygons polypath = model.toSubpathPolygons(m) if config.quality_factor != 1: # Undo the prescaling, if the quality_factor > 1 the curve # quality will be improved. m_inv = QtGui.QTransform.fromScale( 1/config.quality_factor, 1/config.quality_factor) polypath = list(map(m_inv.map, polypath)) # Apply device filters to polypath for f in self.filters: log.debug(" filter | Running {} on polypath".format(f)) polypath = f.apply_to_polypath(polypath) for path in polypath: #: And then each point within the path #: this is a polygon for i, p in enumerate(path): #: Head state # 0 move, 1 cut z = 0 if i == 0 else 1 #: Make a subpath subpath = QtGui.QPainterPath() subpath.moveTo(_p) subpath.lineTo(p) #: Update the last point _p = p #: Total length l = subpath.length() #: If the device does not support streaming #: the path interpolation is skipped entirely if skip_interpolation: x, y = p.x(), p.y() yield (l, self.move, ([x, y, z],), {}) continue #: Where we are within the subpath d = 0 #: Interpolate path in steps of dl and ensure we get #: _p and p (t=0 and t=1) #: This allows us to cancel mid point while d <= l: #: Now set d to the next point by step_size #: if the end of the path is less than the step size #: use the minimum of the two dl = min(l-d, step_size) #: Now find the point at the given step size #: the first point d=0 so t=0, the last point d=l so t=1 t = subpath.percentAtLength(d) sp = subpath.pointAtPercent(t) #if d == l: # break #: Um don't we want to send the last point?? x, y = sp.x(), sp.y() yield (dl, self.move, ([x, y, z],), {}) #: When we reached the end but instead of breaking above #: with a d < l we do it here to ensure we get the last #: point if d == l: #: We reached the end break #: Add step size d += dl #: Make sure we get the endpoint ep = model.currentPosition() x, y = ep.x(), ep.y() yield (0, self.move, ([x, y, 0],), {}) except Exception as e: log.error("device | processing error: {}".format( traceback.format_exc())) raise e
def process(self, model): """ Process the path model of a job and return each command within the job. Parameters ---------- model: QPainterPath The path to process Returns ------- generator: A list or generator object that yields each command to invoke on the device and the distance moved. In the format (distance, cmd, args, kwargs) """ config = self.config #: Previous point _p = QtCore.QPointF(self.origin[0], self.origin[1]) #: Do a final translation since Qt's y axis is reversed t = QtGui.QTransform.fromScale(1, -1) model = model * t #: Determine if interpolation should be used skip_interpolation = (self.connection.always_spools or config.spooled or not config.interpolate) # speed = distance/seconds # So distance/speed = seconds to wait step_size = config.step_size if not skip_interpolation and step_size <= 0: raise ValueError("Cannot have a step size <= 0!") try: #: Some versions of Qt seem to require a value in toSubpathPolygons m = QtGui.QTransform.fromScale(1, 1) for path in model.toSubpathPolygons(m): #: And then each point within the path #: this is a polygon for i, p in enumerate(path): #: Head state # 0 move, 1 cut z = 0 if i == 0 else 1 #: Make a subpath subpath = QtGui.QPainterPath() subpath.moveTo(_p) subpath.lineTo(p) #: Update the last point _p = p #: Total length l = subpath.length() #: If the device does not support streaming #: the path interpolation is skipped entirely if skip_interpolation: x, y = p.x(), p.y() yield (l, self.move, ([x, y, z], ), {}) continue #: Where we are within the subpath d = 0 #: Interpolate path in steps of dl and ensure we get #: _p and p (t=0 and t=1) #: This allows us to cancel mid point while d <= l: #: Now set d to the next point by step_size #: if the end of the path is less than the step size #: use the minimum of the two dl = min(l - d, step_size) #: Now find the point at the given step size #: the first point d=0 so t=0, the last point d=l so t=1 t = subpath.percentAtLength(d) sp = subpath.pointAtPercent(t) #if d == l: # break #: Um don't we want to send the last point?? #: -y because Qt's axis is from top to bottom not bottom #: to top x, y = sp.x(), sp.y() yield (dl, self.move, ([x, y, z], ), {}) #: When we reached the end but instead of breaking above #: with a d < l we do it here to ensure we get the last #: point if d == l: #: We reached the end break #: Add step size d += dl #: Make sure we get the endpoint ep = model.currentPosition() yield (0, self.move, ([ep.x(), ep.y(), 0], ), {}) except Exception as e: log.error("device | processing error: {}".format(e)) raise e