def moveUIPoint(contour, point, delta): if point.segmentType is None: # point is an offCurve. Get its sibling onCurve and the other # offCurve. siblings, shouldMoveAnyway = _getOffCurveSiblingPoints(contour, point) # if an onCurve is selected, the offCurve will move along with it if not (siblings or shouldMoveAnyway): return point.move(delta) for onCurve, otherPoint in siblings: if not onCurve.smooth or otherPoint.selected: continue # if the onCurve is smooth, we need to either... if otherPoint.segmentType is None: # keep the other offCurve inline rotateUIPointAroundRefLine( point.x, point.y, onCurve.x, onCurve.y, otherPoint ) else: # keep point in tangency with onCurve -> otherPoint segment, # i.e. do an orthogonal projection point.x, point.y, _ = bezierMath.lineProjection( onCurve.x, onCurve.y, otherPoint.x, otherPoint.y, point.x, point.y, False, ) else: # point is an onCurve. Move its offCurves along with it. index = contour.index(point) point.move(delta) for d in (-1, 1): # edge-case: contour open, trailing offCurve and moving first # onCurve in contour if contour.open and index == 0 and d == -1: continue pt = contour.getPoint(index + d) if pt.segmentType is None: # avoid double move for qCurve with single offCurve if d > 0: otherPt = contour.getPoint(index + 2 * d) if ( otherPt.segmentType is not None and otherPt.segmentType != "move" and otherPt.selected ): continue pt.move(delta) maybeProjectUISmoothPointOffcurve(contour, index, delta) contour.dirty = True
def _moveOnCurveAlongHandles(self, contour, pt, x, y): ret = False if pt.segmentType is not None: if pt.smooth and len(contour) >= 3: index = contour.index(pt) prevCP = contour.getPoint(index - 1) nextCP = contour.getPoint(index + 1) # we need at least one offCurve so that it makes sense # slide the onCurve around if prevCP.segmentType is None or nextCP.segmentType is None: projX, projY, _ = bezierMath.lineProjection( prevCP.x, prevCP.y, nextCP.x, nextCP.y, x, y, False) # short-circuit UIMove because we're only moving this point pt.x = projX pt.y = projY ret = True else: # non-smooth onCurve we just move, not moving any other point pt.x = x pt.y = y ret = True else: index = contour.index(pt) onCurve = None for delta in (-1, 1): pt_ = contour.getPoint(index + delta) if pt_.segmentType is not None: onCurve = pt_ if onCurve is not None: # keep new pt tangent to onCurve -> pt segment, # i.e. do an orthogonal projection pt.x, pt.y, _ = bezierMath.lineProjection( onCurve.x, onCurve.y, pt.x, pt.y, x, y, False) ret = True if ret: contour.dirty = True return ret
def moveUIPoint(contour, point, delta): if point.segmentType is None: # point is an offCurve. Get its sibling onCurve and the other # offCurve. siblings = _getOffCurveSiblingPoints(contour, point) # if an onCurve is selected, the offCurve will move along with it if not siblings: return point.move(delta) for onCurve, otherPoint in siblings: if not onCurve.smooth: continue # if the onCurve is smooth, we need to either... if otherPoint.segmentType is None and not otherPoint.selected: # keep the other offCurve inline line = QLineF(point.x, point.y, onCurve.x, onCurve.y) otherLine = QLineF( onCurve.x, onCurve.y, otherPoint.x, otherPoint.y) line.setLength(line.length() + otherLine.length()) otherPoint.x = line.x2() otherPoint.y = line.y2() else: # keep point in tangency with onCurve -> otherPoint segment, # i.e. do an orthogonal projection point.x, point.y, _ = bezierMath.lineProjection( onCurve.x, onCurve.y, otherPoint.x, otherPoint.y, point.x, point.y, False) else: # point is an onCurve. Move its offCurves along with it. index = contour.index(point) point.move(delta) for d in (-1, 1): # edge-case: contour open, trailing offCurve and moving first # onCurve in contour if contour.open and index == 0 and d == -1: continue pt = contour.getPoint(index + d) if pt.segmentType is None: # avoid double move for qCurve with single offCurve if d > 0: otherPt = contour.getPoint(index + 2 * d) if otherPt.segmentType is not None and \ otherPt.segmentType != "move" and otherPt.selected: continue pt.move(delta) maybeProjectUISmoothPointOffcurve(contour, point) contour.dirty = True
def _moveOnCurveAlongHandles(self, contour, pt, x, y): # TODO: offCurves if pt.segmentType is not None and pt.smooth and len(contour) >= 3: index = contour.index(pt) prevCP = contour.getPoint(index - 1) nextCP = contour.getPoint(index + 1) # we need at least one offCurve so that it makes sense # slide the onCurve around if prevCP.segmentType is None or nextCP.segmentType is None: projX, projY, _ = bezierMath.lineProjection( prevCP.x, prevCP.y, nextCP.x, nextCP.y, x, y, False) # short-circuit UIMove because we're only moving this point pt.x = projX pt.y = projY contour.dirty = True return True return False
def projectUIPointOnRefLine(x1, y1, x2, y2, pt): x, y, t = bezierMath.lineProjection(x1, y1, x2, y2, pt.x, pt.y, False) # TODO: use grid precision ROUND pt.x = x # round(x) pt.y = y # round(y)