QRect CurveTracker::trackerRect( const QFont &font ) const { QRect r = QwtPlotPicker::trackerRect( font ); // align r to the first curve const QwtPlotItemList curves = plot()->itemList( QwtPlotItem::Rtti_PlotCurve ); if ( curves.size() > 0 ) { QPointF pos = invTransform( trackerPosition() ); const QLineF line = curveLineAt( static_cast<const QwtPlotCurve *>( curves[0] ), pos.x() ); if ( !line.isNull() ) { const double curveY = line.pointAt( ( pos.x() - line.p1().x() ) / line.dx() ).y(); pos.setY( curveY ); pos = transform( pos ); r.moveBottom( pos.y() ); } } return r; }
QPointF CanvasMode_EditSpiral::getSegment(double angle) { PageItem *currItem = m_doc->m_Selection->itemAt(0); PageItem_Spiral *item = currItem->asSpiral(); double ww = item->width(); double wws = 0.0; double wwn = ww; double hh = item->height() - (item->height() / (item->spiralFactor + 1.0)); double segStart = 0.0; double segEnd = 180; bool segPart = true; QPointF ret = QPointF(item->width() / 2.0, item->height() / 2.0); if (angle < 0) return ret; while (true) { QLineF lin = QLineF(QPointF(wws, hh), QPointF(wwn, hh)); if ((angle <= segEnd) && (angle >= segStart)) { ret = lin.pointAt(0.5); break; } ww /= item->spiralFactor; wws = wwn; if (segPart) wwn -= ww; else wwn += ww; segPart = !segPart; segStart += 180.0; segEnd += 180.0; } return ret; }
QString CurveTracker::curveInfoAt( const QwtPlotCurve *curve, const QPointF &pos ) const { const QLineF line = curveLineAt( curve, pos.x() ); if ( line.isNull() ) return QString::null; QPointF p = line.pointAt(( pos.x() - line.p1().x() ) / line.dx()); QString info( "<font color=""%1"">%2 / %3</font>" ); return info.arg( curve->pen().color().name() ).arg( p.y() ).arg(p.x()); }
bool lineBoundedByRect(QLineF& line, QRectF const& rect) { QLineF const rect_lines[4] = { QLineF(rect.topLeft(), rect.topRight()), QLineF(rect.bottomLeft(), rect.bottomRight()), QLineF(rect.topLeft(), rect.bottomLeft()), QLineF(rect.topRight(), rect.bottomRight()) }; double max = NumericTraits<double>::min(); double min = NumericTraits<double>::max(); double s1 = 0; double s2 = 0; BOOST_FOREACH(QLineF const& rect_line, rect_lines) { if (!lineIntersectionScalar(rect_line, line, s1, s2)) { // line is parallel to rect_line. continue; } if (s1 < 0 || s1 > 1) { // Intersection outside of rect. continue; } if (s2 > max) { max = s2; } if (s2 < min) { min = s2; } } if (max > min) { line = QLineF(line.pointAt(min), line.pointAt(max)); return true; } else { return false; } }
QPointF LineObject::objectMidPoint() const { QLineF lyne = line(); QPointF mp = lyne.pointAt(0.5); qreal rot = radians(rotation()); qreal cosRot = qCos(rot); qreal sinRot = qSin(rot); qreal mx = mp.x()*scale(); qreal my = mp.y()*scale(); qreal rotMidX = mx*cosRot - my*sinRot; qreal rotMidY = mx*sinRot + my*cosRot; return (scenePos() + QPointF(rotMidX, rotMidY)); }
const QPointF PortHandler::nearestPort(const QPointF &location, const QStringList &types) const { // location in scene coords, so we map it to mNode. const QPointF locationInLocalCoords = mNode->mapFromScene(location); QPointF nearestPortPoint; qreal minDistance = -1; // just smth negative // Point port observing. QPair<int, qreal> const pointPortRes = nearestPointPortNumberAndDistance(locationInLocalCoords, types); if (pointPortRes.second >= 0) { minDistance = pointPortRes.second; nearestPortPoint = transformPortForNodeSize(mPointPorts[pointPortRes.first]); } // Line port observing. QPair<int, qreal> const linePortRes = nearestLinePortNumberAndDistance(locationInLocalCoords, types); if (linePortRes.second >= 0 && (linePortRes.second < minDistance || minDistance < 0) ) { minDistance = linePortRes.second; const qreal positionAtLineCoef = qMin(qMax(0., nearestPointOfLinePort(linePortRes.first, locationInLocalCoords)) , mMaximumFractionPartValue); const QLineF sceneLine = transformPortForNodeSize(mLinePorts[linePortRes.first]); nearestPortPoint = sceneLine.pointAt(positionAtLineCoef); } QPair<int, qreal> const circularPortRes = nearestCircularPortNumberAndDistance(locationInLocalCoords, types); if (circularPortRes.second >= 0 && (circularPortRes.second < minDistance || minDistance < 0)) { minDistance = circularPortRes.second; nearestPortPoint = coordinateOfCircular(circularPortRes.first, locationInLocalCoords); } if (minDistance > -0.5) { // Moving to scene coords. return nearestPortPoint; } return location; }
GridLineTraverser::GridLineTraverser(QLineF const& line) { QPoint const p1(line.p1().toPoint()); QPoint const p2(line.p2().toPoint()); int h_spans, v_spans, num_spans; double s1 = 0.0, s2 = 0.0; if ((h_spans = abs(p1.x() - p2.x())) > (v_spans = abs(p1.y() - p2.y()))) { // Major direction: horizontal. num_spans = h_spans; lineIntersectionScalar(line, QLineF(p1, QPoint(p1.x(), p1.y() + 1)), s1); lineIntersectionScalar(line, QLineF(p2, QPoint(p2.x(), p2.y() + 1)), s2); } else { // Major direction: vertical. num_spans = v_spans; lineIntersectionScalar(line, QLineF(p1, QPoint(p1.x() + 1, p1.y())), s1); lineIntersectionScalar(line, QLineF(p2, QPoint(p2.x() + 1, p2.y())), s2); } m_dt = num_spans == 0 ? 0 : 1.0 / num_spans; m_line.setP1(line.pointAt(s1)); m_line.setP2(line.pointAt(s2)); m_totalStops = num_spans + 1; m_stopsDone = 0; }
static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold) { int map[4]; bool p1_p2_equal = (orig->x1 == orig->x2 && orig->y1 == orig->y2); bool p2_p3_equal = (orig->x2 == orig->x3 && orig->y2 == orig->y3); bool p3_p4_equal = (orig->x3 == orig->x4 && orig->y3 == orig->y4); QPointF points[4]; int np = 0; points[np] = QPointF(orig->x1, orig->y1); map[0] = 0; ++np; if (!p1_p2_equal) { points[np] = QPointF(orig->x2, orig->y2); ++np; } map[1] = np - 1; if (!p2_p3_equal) { points[np] = QPointF(orig->x3, orig->y3); ++np; } map[2] = np - 1; if (!p3_p4_equal) { points[np] = QPointF(orig->x4, orig->y4); ++np; } map[3] = np - 1; if (np == 1) return Discard; // We need to specialcase lines of 3 or 4 points due to numerical // instability in intersections below if (np > 2 && qbezier_is_line(points, np)) { if (points[0] == points[np-1]) return Discard; QLineF l = qline_shifted(points[0], points[np-1], offset); *shifted = QBezier::fromPoints(l.p1(), l.pointAt(qreal(0.33)), l.pointAt(qreal(0.66)), l.p2()); return Ok; } QRectF b = orig->bounds(); if (np == 4 && b.width() < .1*offset && b.height() < .1*offset) { qreal l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) + (orig->y1 - orig->y2)*(orig->y1 - orig->y1) * (orig->x3 - orig->x4)*(orig->x3 - orig->x4) + (orig->y3 - orig->y4)*(orig->y3 - orig->y4); qreal dot = (orig->x1 - orig->x2)*(orig->x3 - orig->x4) + (orig->y1 - orig->y2)*(orig->y3 - orig->y4); if (dot < 0 && dot*dot < 0.8*l) // the points are close and reverse dirction. Approximate the whole // thing by a semi circle return Circle; } QPointF points_shifted[4]; QLineF prev = QLineF(QPointF(), points[1] - points[0]); QPointF prev_normal = prev.normalVector().unitVector().p2(); points_shifted[0] = points[0] + offset * prev_normal; for (int i = 1; i < np - 1; ++i) { QLineF next = QLineF(QPointF(), points[i + 1] - points[i]); QPointF next_normal = next.normalVector().unitVector().p2(); QPointF normal_sum = prev_normal + next_normal; qreal r = 1.0 + prev_normal.x() * next_normal.x() + prev_normal.y() * next_normal.y(); if (qFuzzyIsNull(r)) { points_shifted[i] = points[i] + offset * prev_normal; } else { qreal k = offset / r; points_shifted[i] = points[i] + k * normal_sum; } prev_normal = next_normal; } points_shifted[np - 1] = points[np - 1] + offset * prev_normal; *shifted = QBezier::fromPoints(points_shifted[map[0]], points_shifted[map[1]], points_shifted[map[2]], points_shifted[map[3]]); return good_offset(orig, shifted, offset, threshold); }