void RGraphicsSceneQt::exportRay(const RRay& ray) { bool created = beginPath(); Q_ASSERT(currentPainterPath.isValid()); // find largest view box over all attached views: RBox box; QList<RGraphicsView*>::iterator it; for (it=views.begin(); it!=views.end(); it++) { RBox b = (*it)->getBox(); box.growToIncludeBox(b); } // trim line to view box: RLine clippedLine = ray.getClippedLine(box); double offs = clippedLine.getStartPoint().getDistanceTo(ray.getBasePoint()); if (RMath::isSameDirection(ray.getBasePoint().getAngleTo(clippedLine.getStartPoint()), ray.getDirection1())) { offs *= -1; } exportLine(clippedLine, offs); currentPainterPath.setAlwaysRegen(true); if (created) { endPath(); } }
void RGraphicsSceneQt::exportEllipse(const REllipse& ellipse, double offset) { bool created = beginPath(); RGraphicsScene::exportEllipse(ellipse, offset); if (created) { endPath(); } }
void RGraphicsSceneQt::exportSpline(const RSpline& spline, double offset) { bool created = beginPath(); RGraphicsScene::exportSpline(spline, offset); if (created) { endPath(); } }
void RGraphicsSceneQt::exportArc(const RArc& arc, double offset, double w1, double w2) { bool created = beginPath(); RGraphicsScene::exportArc(arc, offset, w1, w2); if (created) { endPath(); } }
void RGraphicsSceneQt::exportPoint(const RPoint& point) { bool created = beginPath(); currentPainterPath.addPoint(point.position); if (created) { endPath(); } }
void RGraphicsSceneQt::exportPolyline(const RPolyline& polyline, bool polylineGen, double offset) { // filling: bool created = beginPath(); exportPolylineFill(polyline); if (created) { endPath(); } // outline: created = beginPath(); RGraphicsScene::exportPolyline(polyline, polylineGen, offset); if (created) { endPath(); } }
double RGraphicsSceneQt::exportLine(const RLine& line, double offset, double w1, double w2) { bool created = beginPath(); bool ret = RGraphicsScene::exportLine(line, offset, w1, w2); if (created) { endPath(); } return ret; }
void RGraphicsSceneQt::exportThickArc(const RArc& arc, double w1, double w2) { if (RPolyline::hasProxy()) { bool hasCurrentPath = false; if (currentPainterPath.isValid()) { hasCurrentPath = true; endPath(); } beginPath(); RPolyline::getPolylineProxy()->exportThickArc(currentPainterPath, arc, w1, w2); currentPainterPath.setBrush(currentPen.color()); currentPainterPath.setPen(QPen(Qt::NoPen)); endPath(); if (hasCurrentPath) { beginPath(); } } else { exportArc(arc); } }
void RGraphicsSceneQt::exportPolylineFill(const RPolyline& polyline) { if (currentBrush!=Qt::NoBrush) { bool created = beginPath(); // TODO: support arc segments for filling: QPolygonF qpolygon; QList<RVector> points = polyline.getVertices(); for (int i = 0; i < points.size(); ++i) { RVector v = points.at(i); qpolygon << QPointF(v.x, v.y); } currentPainterPath.setBrush(currentBrush); currentPainterPath.addPolygon(qpolygon); if (created) { endPath(); } } }
void KoCreatePathTool::mouseReleaseEvent(KoPointerEvent *event) { Q_D(KoCreatePathTool); if (! d->shape || (event->buttons() & Qt::RightButton)) return; d->listeningToModifiers = true; // After the first press-and-release d->repaintActivePoint(); d->pointIsDragged = false; KoPathPoint *lastActivePoint = d->activePoint; if (!d->finishAfterThisPoint) { d->activePoint = d->shape->lineTo(event->point); canvas()->snapGuide()->setIgnoredPathPoints((QList<KoPathPoint*>()<<d->activePoint)); } // apply symmetric point property if applicable if (lastActivePoint->activeControlPoint1() && lastActivePoint->activeControlPoint2()) { QPointF diff1 = lastActivePoint->point() - lastActivePoint->controlPoint1(); QPointF diff2 = lastActivePoint->controlPoint2() - lastActivePoint->point(); if (qFuzzyCompare(diff1.x(), diff2.x()) && qFuzzyCompare(diff1.y(), diff2.y())) lastActivePoint->setProperty(KoPathPoint::IsSymmetric); } if (d->finishAfterThisPoint) { d->firstPoint->setControlPoint1(d->activePoint->controlPoint1()); delete d->shape->removePoint(d->shape->pathPointIndex(d->activePoint)); d->activePoint = d->firstPoint; d->shape->closeMerge(); // we are closing the path, so reset the existing start path point d->existingStartPoint = 0; // finish path endPath(); } if (d->angleSnapStrategy && lastActivePoint->activeControlPoint2()) { d->angleSnapStrategy->deactivate(); } }
void KoCreatePathTool::mousePressEvent(KoPointerEvent *event) { Q_D(KoCreatePathTool); //Right click removes last point if (event->button() == Qt::RightButton) { removeLastPoint(); return; } const bool isOverFirstPoint = d->shape && handleGrabRect(d->firstPoint->point()).contains(event->point); bool haveCloseModifier = (listeningToModifiers() && (event->modifiers() & Qt::ShiftModifier)); if ((event->button() == Qt::LeftButton) && haveCloseModifier && !isOverFirstPoint) { endPathWithoutLastPoint(); return; } d->finishAfterThisPoint = false; if (pathStarted()) { if (isOverFirstPoint) { d->activePoint->setPoint(d->firstPoint->point()); canvas()->updateCanvas(d->shape->boundingRect()); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); if (haveCloseModifier) { d->shape->closeMerge(); // we are closing the path, so reset the existing start path point d->existingStartPoint = 0; // finish path endPath(); } else { // the path shape will get closed when the user releases // the mouse button d->finishAfterThisPoint = true; } } else { canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); QPointF point = canvas()->snapGuide()->snap(event->point, event->modifiers()); // check whether we hit an start/end node of an existing path d->existingEndPoint = d->endPointAtPosition(point); if (d->existingEndPoint.isValid() && d->existingEndPoint != d->existingStartPoint) { point = d->existingEndPoint.path->shapeToDocument(d->existingEndPoint.point->point()); d->activePoint->setPoint(point); // finish path endPath(); } else { d->activePoint->setPoint(point); canvas()->updateCanvas(d->shape->boundingRect()); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); } } } else { KoPathShape *pathShape = new KoPathShape(); d->shape=pathShape; pathShape->setShapeId(KoPathShapeId); KoShapeStroke *stroke = new KoShapeStroke(canvas()->resourceManager()->activeStroke()); stroke->setColor(canvas()->resourceManager()->foregroundColor().toQColor()); pathShape->setStroke(stroke); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); QPointF point = canvas()->snapGuide()->snap(event->point, event->modifiers()); // check whether we hit an start/end node of an existing path d->existingStartPoint = d->endPointAtPosition(point); if (d->existingStartPoint.isValid()) { point = d->existingStartPoint.path->shapeToDocument(d->existingStartPoint.point->point()); } d->activePoint = pathShape->moveTo(point); d->firstPoint = d->activePoint; canvas()->updateCanvas(handlePaintRect(point)); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); canvas()->snapGuide()->setEditedShape(pathShape); d->angleSnapStrategy = new AngleSnapStrategy(d->angleSnappingDelta, d->angleSnapStatus); canvas()->snapGuide()->addCustomSnapStrategy(d->angleSnapStrategy); } if (d->angleSnapStrategy) d->angleSnapStrategy->setStartPoint(d->activePoint->point()); }
/* genEllipticPath: * Approximate an elliptical arc via Beziers of given degree * threshold indicates quality of approximation * if isSlice is true, the path begins and ends with line segments * to the center of the ellipse. * Returned path must be freed by the caller. */ static Ppolyline_t *genEllipticPath(ellipse_t * ep, int degree, double threshold, boolean isSlice) { double dEta; double etaB; double cosEtaB; double sinEtaB; double aCosEtaB; double bSinEtaB; double aSinEtaB; double bCosEtaB; double xB; double yB; double xBDot; double yBDot; double t; double alpha; Ppolyline_t *path = NEW(Ppolyline_t); // find the number of Bezier curves needed boolean found = FALSE; int i, n = 1; while ((!found) && (n < 1024)) { double dEta = (ep->eta2 - ep->eta1) / n; if (dEta <= 0.5 * M_PI) { double etaB = ep->eta1; found = TRUE; for (i = 0; found && (i < n); ++i) { double etaA = etaB; etaB += dEta; found = (estimateError(ep, degree, etaA, etaB) <= threshold); } } n = n << 1; } dEta = (ep->eta2 - ep->eta1) / n; etaB = ep->eta1; cosEtaB = cos(etaB); sinEtaB = sin(etaB); aCosEtaB = ep->a * cosEtaB; bSinEtaB = ep->b * sinEtaB; aSinEtaB = ep->a * sinEtaB; bCosEtaB = ep->b * cosEtaB; xB = ep->cx + aCosEtaB * ep->cosTheta - bSinEtaB * ep->sinTheta; yB = ep->cy + aCosEtaB * ep->sinTheta + bSinEtaB * ep->cosTheta; xBDot = -aSinEtaB * ep->cosTheta - bCosEtaB * ep->sinTheta; yBDot = -aSinEtaB * ep->sinTheta + bCosEtaB * ep->cosTheta; if (isSlice) { moveTo(path, ep->cx, ep->cy); lineTo(path, xB, yB); } else { moveTo(path, xB, yB); } t = tan(0.5 * dEta); alpha = sin(dEta) * (sqrt(4 + 3 * t * t) - 1) / 3; for (i = 0; i < n; ++i) { double xA = xB; double yA = yB; double xADot = xBDot; double yADot = yBDot; etaB += dEta; cosEtaB = cos(etaB); sinEtaB = sin(etaB); aCosEtaB = ep->a * cosEtaB; bSinEtaB = ep->b * sinEtaB; aSinEtaB = ep->a * sinEtaB; bCosEtaB = ep->b * cosEtaB; xB = ep->cx + aCosEtaB * ep->cosTheta - bSinEtaB * ep->sinTheta; yB = ep->cy + aCosEtaB * ep->sinTheta + bSinEtaB * ep->cosTheta; xBDot = -aSinEtaB * ep->cosTheta - bCosEtaB * ep->sinTheta; yBDot = -aSinEtaB * ep->sinTheta + bCosEtaB * ep->cosTheta; if (degree == 1) { lineTo(path, xB, yB); #if DO_QUAD } else if (degree == 2) { double k = (yBDot * (xB - xA) - xBDot * (yB - yA)) / (xADot * yBDot - yADot * xBDot); quadTo(path, (xA + k * xADot), (yA + k * yADot), xB, yB); #endif } else { curveTo(path, (xA + alpha * xADot), (yA + alpha * yADot), (xB - alpha * xBDot), (yB - alpha * yBDot), xB, yB); } } endPath(path, isSlice); return path; }