QPolygonF PageLayout::rightPageOutline() const { if (m_uncutOutline.size() < 4) { return QPolygonF(); } switch (m_type) { case SINGLE_PAGE_UNCUT: case SINGLE_PAGE_CUT: return QPolygonF(); case TWO_PAGES: break; } QLineF const line1(m_uncutOutline[1], m_uncutOutline[2]); QLineF line2(extendToCover(m_cutter1, m_uncutOutline)); ensureSameDirection(line1, line2); QLineF const reverse_line1(line1.p2(), line1.p1()); QLineF const reverse_line2(line2.p2(), line2.p1()); QPolygonF poly; poly << line1.p1(); maybeAddIntersectionPoint(poly, line1.normalVector(), line2.normalVector()); poly << line2.p1() << line2.p2(); maybeAddIntersectionPoint(poly, reverse_line1.normalVector(), reverse_line2.normalVector()); poly << line1.p2(); return PolygonUtils::round(m_uncutOutline).intersected(PolygonUtils::round(poly)); }
/** @param point Un point donne @param line Un segment de droite donnee @param intersection si ce pointeur est different de 0, le QPointF ainsi designe contiendra les coordonnees du projete orthogonal, meme si celui-ci n'appartient pas au segment de droite @return true si le projete orthogonal du point sur la droite appartient au segment de droite. */ bool QET::orthogonalProjection(const QPointF &point, const QLineF &line, QPointF *intersection) { // recupere le vecteur normal de `line' QLineF line_normal_vector(line.normalVector()); QPointF normal_vector(line_normal_vector.dx(), line_normal_vector.dy()); // cree une droite perpendiculaire a `line' passant par `point' QLineF perpendicular_line(point, point + normal_vector); // determine le point d'intersection des deux droites = le projete orthogonal QPointF intersection_point; QLineF::IntersectType it = line.intersect(perpendicular_line, &intersection_point); // ne devrait pas arriver (mais bon...) if (it == QLineF::NoIntersection) return(false); // fournit le point d'intersection a l'appelant si necessaire if (intersection) { *intersection = intersection_point; } // determine si le point d'intersection appartient au segment de droite if (QET::lineContainsPoint(line, intersection_point)) { return(true); } return(false); }
QPainterPath CopyFilterGUIConnectionItem::shape() const { QLineF l = line(); QPainterPath path; path.setFillRule(Qt::WindingFill); double length = line().length(); if (length > 0) { double offset = min(length, maxArrowSize); QLineF unit = l.unitVector(); QLineF normal = l.normalVector().unitVector(); QPointF v(unit.dx(), unit.dy()); QPointF n(normal.dx(), normal.dy()); QPointF p2 = l.p2(); QPointF p3 = p2 - v * offset + 0.5 * n * offset; QPointF p4 = p2 - v * offset - 0.5 * n * offset; QPolygonF polygon; polygon.append(p4); polygon.append(p3); polygon.append(p2); path.addPolygon(polygon); QPolygonF polygon2; QPointF p1 = l.p1(); polygon2.append(p2 + 3 * n); polygon2.append(p2 - 2 * n); polygon2.append(p1 - 2 * n); polygon2.append(p1 + 3 * n); path.addPolygon(polygon2); if (factor != 1.0 || isDecibel) { QFont font; font.setPixelSize(10); QPointF center = (l.p1() + l.p2()) / 2; QString text = QString("%1").arg(factor); if (isDecibel) text += " dB"; QFontMetrics fontMetrics(font); QSizeF size = fontMetrics.size(0, text); size += QSizeF(2, 0); QRectF rect; rect.setSize(size); rect.moveCenter(center); path.addRoundedRect(rect.adjusted(-0.5, 0.5, 0.5, 0.5), 3, 3); } } return path; }
QPolygonF QGVEdge::toBox(const QLineF &line) const { QLineF n = line.normalVector(); QPointF o(n.dx() * 0.5, n.dy() * 0.5); QPolygonF polygon; polygon.append(line.p1() + o); polygon.append(line.p2() + o); polygon.append(line.p2() - o); polygon.append(line.p1() - o); return polygon; }
QPolygonF QGVEdge::toArrow(const QLineF &line) const { QLineF n = line.normalVector(); QPointF o(n.dx() / 3.0, n.dy() / 3.0); //Only support normal arrow type QPolygonF polygon; polygon.append(line.p1() + o); polygon.append(line.p2()); polygon.append(line.p1() - o); return polygon; }
bool GraphConnection::isPointing(const QRectF &rect) const { //check individual line segments for (int i = 1; i < _impl->points.size(); i++) { const QLineF line(_impl->points[i-1], _impl->points[i]); QLineF norm = line.normalVector(); norm.setLength(GraphConnectionSelectPad); if (QRectF(line.p2(), norm.p2()).intersects(rect)) return true; } //check arrow head return not _impl->arrowHead.intersected(rect).isEmpty(); }
void CopyFilterGUIConnectionItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { QLineF l = line(); if (!l.isNull()) { painter->setBrush(Qt::black); if (isSelected()) { painter->setBrush(Qt::blue); painter->setPen(QPen(Qt::blue, 1.5)); } painter->drawLine(line()); double length = line().length(); double offset = min(length, maxArrowSize); QLineF unit = l.unitVector(); QLineF normal = l.normalVector().unitVector(); QPointF v(unit.dx(), unit.dy()); QPointF n(normal.dx(), normal.dy()); QPointF p2 = l.p2(); QPointF p3 = p2 - v * offset + 0.5 * n * offset; QPointF p4 = p2 - v * offset - 0.5 * n * offset; QPolygonF polygon; polygon.append(p2); polygon.append(p3); polygon.append(p4); painter->drawPolygon(polygon); if (factor != 1.0 || isDecibel) { QFont font = painter->font(); font.setPixelSize(10); painter->setFont(font); QPointF center = (l.p1() + l.p2()) / 2; QString text = QString("%1").arg(factor); if (isDecibel) text += " dB"; QSizeF size = painter->fontMetrics().size(0, text); size += QSizeF(2, 0); QRectF rect; rect.setSize(size); rect.moveCenter(center); painter->setBrush(Qt::white); painter->drawRoundedRect(rect.adjusted(-0.5, 0.5, 0.5, 0.5), 3, 3); painter->drawText(rect, Qt::AlignCenter, text); } } }
bool TextLineTracer::isInsideBounds( QPointF const& pt, QLineF const& left_bound, QLineF const& right_bound) { QPointF left_normal_inside(left_bound.normalVector().p2() - left_bound.p1()); if (left_normal_inside.x() < 0) { left_normal_inside = -left_normal_inside; } QPointF const left_vec(pt - left_bound.p1()); if (left_normal_inside.x() * left_vec.x() + left_normal_inside.y() * left_vec.y() < 0) { return false; } QPointF right_normal_inside(right_bound.normalVector().p2() - right_bound.p1()); if (right_normal_inside.x() > 0) { right_normal_inside = -right_normal_inside; } QPointF const right_vec(pt - right_bound.p1()); if (right_normal_inside.x() * right_vec.x() + right_normal_inside.y() * right_vec.y() < 0) { return false; } return true; }
void GraphicsPathItem::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->setPen (QPen (QBrush (*_color), 0.1, Qt::SolidLine)); painter->setBrush (QBrush (*_color)); painter->drawLine (_start, _end); QPainterPath path; QLineF unit = QLineF (_start, _end).unitVector (); QLineF normal = unit.normalVector (); QPointF u (unit.dx (), unit.dy ()); QPointF v (normal.dx (), normal.dy ()); QPointF middle = 0.5 * (QPointF(_start) + QPointF (_end)); path.moveTo (middle + 0.4*u); path.lineTo (middle - 0.2*u + 0.2*v); path.lineTo (middle - 0.2*u - 0.2*v); path.closeSubpath (); painter->drawPath (path); }
void SplineTransferFunction::updateNormals() { m_normals.clear(); m_rightNormals.clear(); m_leftNormals.clear(); for (int i=0; i<m_points.size(); ++i) { QLineF ln; if (i == 0) ln = QLineF(m_points[i], m_points[i+1]); else if (i == m_points.size()-1) ln = QLineF(m_points[i-1], m_points[i]); else ln = QLineF(m_points[i-1], m_points[i+1]); QLineF unitVec; if (ln.length() > 0) unitVec = ln.normalVector().unitVector(); else unitVec = QLineF(QPointF(0,0), QPointF(1,0)); unitVec.translate(-unitVec.p1()); float a = m_normalRotations[i]; QPointF p1 = unitVec.p2(); QPointF p2; p2.setX(p1.x()*cos(a) + p1.y()*sin(a)); p2.setY(-p1.x()*sin(a) + p1.y()*cos(a)); unitVec = QLineF(QPointF(0,0), p2); QPointF v1, v2; v1 = m_points[i] + m_normalWidths[i].x()*unitVec.p2(); v2 = m_points[i] - m_normalWidths[i].y()*unitVec.p2(); m_normals << unitVec.p2(); m_rightNormals << v1; m_leftNormals << v2; } }
void VBezier::editPoints(QPointF p, VElement::EditAction action) { static bool isDraging = false; static int currentNode; static int param; if(action == CLICK) { for(uint i=0;i<nodes.size();i++) { if(QLineF(nodes[i].p, p).length() < 6) { currentNode = i; param = 0; isDraging = true; } if(QLineF(nodes[i].c1, p).length() < 6) { currentNode = i; param = 1; isDraging = true; } if(QLineF(nodes[i].c2, p).length() < 6) { currentNode = i; param = 2; isDraging = true; } } } else if(action == DRAG) { if(isDraging) { if(param == 0) { VBezier::Node &n = nodes[currentNode]; QPointF delta = p - n.p; n.p += delta; n.c1 += delta; n.c2 += delta; } else if(param == 1) { VBezier::Node &n = nodes[currentNode]; QPointF delta = n.p - p; n.c1 = p; n.c2= n.p + delta; } if(param == 2) { VBezier::Node &n = nodes[currentNode]; QPointF delta = n.p - p; n.c1= n.p + delta; n.c2 = p; } rebuildBB(); } } else if(action == RELEASE) { isDraging = false; } else if(action == ADDPOINT) { std::vector<int> distanceToSide; int min = 0; nodes.push_back(nodes[0]); // dla linii między pierwszym i ostatnim wierzchołkiem for(uint i=0;i<nodes.size()-1;i++) { qreal distToA = QLineF(nodes[i].p, p).length(); qreal distToB = QLineF(nodes[i+1].p, p).length(); QLineF v(nodes[i].p, p); QLineF unit = QLineF(nodes[i].p, nodes[i+1].p).unitVector(); QLineF normal = unit.normalVector(); qreal proj = unit.dx()*v.dx() + unit.dy()*v.dy(); qreal distToLine = fabs(normal.dx()*v.dx() + normal.dy()*v.dy()); if(proj<0) distToLine = distToA; if(proj>QLineF(nodes[i].p, nodes[i+1].p).length()) distToLine = distToB; distanceToSide.push_back(distToLine); if(distanceToSide[i] < distanceToSide[min]) min = i; } nodes.pop_back(); min+=1; if(min == nodes.size()) { qreal distToFirst = QLineF(nodes[0].p, p).length(); qreal distToLast = QLineF(nodes[min-1].p, p).length(); if(distToFirst < distToLast) { min = 0; } } Node newNode; newNode.p = p; newNode.c1 = p; newNode.c2 = p; nodes.insert(nodes.begin() + min, newNode); currentNode = min; isDraging = true; param = 2; rebuildBB(); } else if(action == DELETEPOINT) { for(uint i=0;i<nodes.size();i++) { if(QLineF(nodes[i].p, p).length() < 6) { nodes.erase(nodes.begin()+i); rebuildBB(); break; } } } }
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; 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 = qreal(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); }