Dubins::Dubins(const QVector2D &posA, qreal angleA, const QVector2D &posB, qreal angleB, qreal minTurnRadius) : _posA(posA.toPointF()), _angleA(angleA), _posB(posB.toPointF()), _angleB(angleB), _minTurnRadius(minTurnRadius), _isValid(false) { _solvePath(); }
float SCgBus::dotPos(const QPointF &point) const { // get sector with minimal distance to point // and calculates relative dot position on it qreal minDist = -1.f; qreal result = 0.f; QPointF np = mapFromScene(point); for (int i = 1; i < mPoints.size(); i++) { QPointF p1 = mPoints[i - 1]; QPointF p2 = mPoints[i]; QVector2D v(p2 - p1); QVector2D vp(np - p1); QVector2D vn = v.normalized(); //vp.normalize(); // calculate point on line QVector2D p = QVector2D(p1) + vn * QVector2D::dotProduct(vn, vp); if(v.length() == 0) return result; qreal dotPos = QVector2D(p.toPointF() - p1).length() / v.length(); if (dotPos < 0.f || dotPos > 1.f) continue; // we doesn't need to get real length, because we need minimum // so we get squared length to make that procedure faster qreal d = QVector2D(np - p.toPointF()).lengthSquared(); // compare with minimum distance if (minDist < 0.f || minDist > d) { minDist = d; result = (i - 1) + dotPos; } } return result; }
void NeuroLinkItem::adjustLinks() { QVector2D front(_line.p2()); QVector2D back(_line.p1()); QVector2D center = front + (c2 - front) * 0.33 + (back - front) * 0.1; foreach (NeuroItem *ni, _incoming) { MixinArrow *link = dynamic_cast<MixinArrow *>(ni); if (link) link->setLine(link->line().p1(), mapToScene(center.toPointF())); }
void Car::advance(int phase) { if( phase == 0 ) { return; } if( ! scene()->cellBlocked(this) ) { QRectF carRect = boundingRect(); QVector2D v = QVector2D(targetPoint - startPoint) / 100.0 * progress; carRect.moveCenter( v.toPointF() + startPoint ); setPos(carRect.topLeft()); progress += progressDelta; if( progress >= 100 ) { _direction = targetDirection; setCell( targetCellRow, targetCellCol ); progress %= 100; } update(); } }
QLineF Geometry::veryLongLine(QPointF const &pointOnLine, QVector2D const &directionVector) { qreal const halfLength = 10000; return QLineF(pointOnLine + halfLength * directionVector.toPointF() , pointOnLine - halfLength * directionVector.toPointF()); }
/* draw an angle from the current point to b and then to c, * with a rounded corner of the given radius. */ void KeyboardLayoutWidget::roundedCorner (QPainterPath& path, QPointF b, QPointF c, double radius) { /* we may have 5 point here * a is the current point * c is the end point * and b is the corner * we will have a rounded corner with radious (maybe adjust by a,b,c position) * * a1 is on a-b, and c1 is on b-c */ QPointF a = path.currentPosition(); //qDebug() << "current" << a << b << c; /* make sure radius is not too large */ double dist1 = distance (a, b); double dist2 = distance (b, c); //qDebug() << "dist" << dist1 << dist2 << radius; radius = qMin (radius, qMin (dist1, dist2)); QPointF ba = a - b; QPointF bc = c - b; QVector2D na(ba); QVector2D nc(bc); na.normalize(); nc.normalize(); qreal cosine = QVector2D::dotProduct(na, nc); qreal halfcosine = qSqrt((1 + cosine) / 2); qreal halfsine = qSqrt( 1- halfcosine * halfcosine); qreal halftan = halfsine / halfcosine; QPointF a1 = b + na.toPointF() * (radius / halftan); QPointF c1 = b + nc.toPointF() * (radius / halftan); QVector2D n = na + nc; n.normalize(); QPointF ctr = b + n.toPointF() * radius / halfsine; QRectF arcRect(ctr.x() - radius, ctr.y() - radius, 2 * radius, 2 * radius); qreal phiA, phiC; //qDebug() << c1 << ctr << a1; QVector2D ctra = QVector2D(a1 - ctr); QVector2D ctrc = QVector2D(c1 - ctr); ctra.normalize(); ctrc.normalize(); phiA = angle(ctra); phiC = angle(ctrc); qreal delta = phiC - phiA; while (delta > 0) delta -= 360; while (delta < -360) delta += 360; if (delta <- 180) delta += 360; //qDebug() << arcRect << ctra << ctrc << ctr << "degree" << phiA << phiC; path.lineTo(a1); path.arcTo(arcRect, phiA, delta); path.lineTo(c1); path.lineTo(c); }
/*! \internal Draws the line ending with the specified \a painter at the position \a pos. The direction of the line ending is controlled with \a dir. */ void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const { if (mStyle == esNone) return; QVector2D lengthVec(dir.normalized()); if (lengthVec.isNull()) lengthVec = QVector2D(1, 0); QVector2D widthVec(-lengthVec.y(), lengthVec.x()); lengthVec *= (float)(mLength*(mInverted ? -1 : 1)); widthVec *= (float)(mWidth*0.5*(mInverted ? -1 : 1)); QPen penBackup = painter->pen(); QBrush brushBackup = painter->brush(); QPen miterPen = penBackup; miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey QBrush brush(painter->pen().color(), Qt::SolidPattern); switch (mStyle) { case esNone: break; case esFlatArrow: { QPointF points[3] = {pos.toPointF(), (pos-lengthVec+widthVec).toPointF(), (pos-lengthVec-widthVec).toPointF() }; painter->setPen(miterPen); painter->setBrush(brush); painter->drawConvexPolygon(points, 3); painter->setBrush(brushBackup); painter->setPen(penBackup); break; } case esSpikeArrow: { QPointF points[4] = {pos.toPointF(), (pos-lengthVec+widthVec).toPointF(), (pos-lengthVec*0.8f).toPointF(), (pos-lengthVec-widthVec).toPointF() }; painter->setPen(miterPen); painter->setBrush(brush); painter->drawConvexPolygon(points, 4); painter->setBrush(brushBackup); painter->setPen(penBackup); break; } case esLineArrow: { QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(), pos.toPointF(), (pos-lengthVec-widthVec).toPointF() }; painter->setPen(miterPen); painter->drawPolyline(points, 3); painter->setPen(penBackup); break; } case esDisc: { painter->setBrush(brush); painter->drawEllipse(pos.toPointF(), mWidth*0.5, mWidth*0.5); painter->setBrush(brushBackup); break; } case esSquare: { QVector2D widthVecPerp(-widthVec.y(), widthVec.x()); QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(), (pos-widthVecPerp-widthVec).toPointF(), (pos+widthVecPerp-widthVec).toPointF(), (pos+widthVecPerp+widthVec).toPointF() }; painter->setPen(miterPen); painter->setBrush(brush); painter->drawConvexPolygon(points, 4); painter->setBrush(brushBackup); painter->setPen(penBackup); break; } case esDiamond: { QVector2D widthVecPerp(-widthVec.y(), widthVec.x()); QPointF points[4] = {(pos-widthVecPerp).toPointF(), (pos-widthVec).toPointF(), (pos+widthVecPerp).toPointF(), (pos+widthVec).toPointF() }; painter->setPen(miterPen); painter->setBrush(brush); painter->drawConvexPolygon(points, 4); painter->setBrush(brushBackup); painter->setPen(penBackup); break; } case esBar: { painter->drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF()); break; } case esHalfBar: { painter->drawLine((pos+widthVec).toPointF(), pos.toPointF()); break; } case esSkewedBar: { if (qFuzzyIsNull(painter->pen().widthF()) && !painter->modes().testFlag(QCPPainter::pmNonCosmetic)) { // if drawing with cosmetic pen (perfectly thin stroke, happens only in vector exports), draw bar exactly on tip of line painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)).toPointF(), (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)).toPointF()); } else { // if drawing with thick (non-cosmetic) pen, shift bar a little in line direction to prevent line from sticking through bar slightly painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF(), (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF()); } break; } } }