void QChain::cutCircle(Circle circle) { if (m_vertices.size() == 0) return; circle.setCenter(circle.pos()); QPainterPath cr; cr.addEllipse(circle.x - circle.r, circle.y - circle.r, 2 * circle.r, 2 * circle.r); QPolygonF polygon; for (QPointF p : m_vertices) polygon.append(p); QPainterPath chain; chain.addPolygon(polygon); if (!chain.intersects(cr)) return; chain = chain.subtracted(cr); for (const QPolygonF &poly : chain.toSubpathPolygons()) { std::vector<Vector2d> pts(poly.begin(), poly.end() - 1); if (std::fabs(Geometry::area(pts.begin(), pts.end())) > 5.f) { auto chain = std::make_unique<QChain>(world()); chain->setVertices(std::vector<QPointF>(pts.begin(), pts.end())); chain->initializeLater(world()); world()->itemSet()->addBody(std::move(chain)); } } m_vertices.clear(); destroyLater(); }
TrackActivities ViewInteractionItemDrawer::AddTrackingVertex( const QPointF &src, bool force) { QPainterPath p = _vitem->path(); QList<QPolygonF> ps = p.toSubpathPolygons(); Q_ASSERT(ps.size() <= 1); Q_ASSERT(_vitem->_feature != nullptr); Q_ASSERT(_vitem->_feature->paths().size() == 1); _vitem->ClearTempItems(); TrackActivities ret; int n = _vitem->_feature->get_geometry(0).size(); if (n == 0) { ret = TryTrackingMulti(src); if (force && ret.is_tracked()) { _vitem->add_temp_vertex(ret.closest()._vpos); } } else { Q_ASSERT(p.elementCount() == n || p.elementCount() == n + 1); if (p.elementCount() == n) { p.lineTo(src); } else { ret = TryTrackingMulti(src); if (force && ret.is_tracked()) { p.setElementPositionAt(n, ret.closest()._vpos.x(), ret.closest()._vpos.y()); _vitem->add_temp_vertex(ret.closest()._vpos); } else { p.setElementPositionAt(n, src.x(), src.y()); } } } _vitem->setPath(p); return force ? ret : TrackActivities(); }
bool SmoothPathPlugin::run(ScribusDoc* doc, QString) { ScribusDoc* currDoc = doc; if (currDoc == 0) currDoc = ScCore->primaryMainWindow()->doc; if (currDoc->m_Selection->count() > 0) { PageItem *currItem = currDoc->m_Selection->itemAt(0); QPainterPath pp; if (currItem->itemType() == PageItem::PolyLine) pp = currItem->PoLine.toQPainterPath(false); else pp = currItem->PoLine.toQPainterPath(true); QList<QPolygonF> polyList = pp.toSubpathPolygons(); QPainterPath result; for (int a = 0; a < polyList.count(); a++) { result.addPath(bezierFit(polyList[a], 5.0)); } currItem->PoLine.fromQPainterPath(result); currItem->ClipEdited = true; currItem->FrameType = 3; currDoc->AdjustItemSize(currItem); currItem->OldB2 = currItem->width(); currItem->OldH2 = currItem->height(); currItem->updateClip(); currDoc->regionsChanged()->update(QRectF()); currDoc->changed(); } return true; }
/** * Este método dibuja una línea de texto. * @brief ThreeDWriter::writeLine * @param textLine Linea de texto a escribir * @param px coordenada x de donde comenzar a escribir * @param py coordenada y de donde comenzar a escribir * @param pz coordenada z de donde comenzar a escribir */ void ThreeDWriter::writeLine(QString textLine) { QPainterPath path; glDisable(GL_LIGHTING); glColor3f (0.1f, 0.1f, 0.1f); QFont font(this->fontName, this->fontSize); path.addText(QPointF(0, 0), font, textLine); QList<QPolygonF> poly = path.toSubpathPolygons(); for (QList<QPolygonF>::iterator i = poly.begin(); i != poly.end(); i++){ glBegin(GL_LINE_LOOP); for (QPolygonF::iterator p = (*i).begin(); p != i->end(); p++){ this->x = p->rx()*this->cof+this->start_x; this->y = p->ry()*this->cof+this->start_y; this->z = this->start_z; glVertex3f(this->x, this->y, this->z); //qDebug()<<"Escribiendo en x:"<<x<<" y"<<y<< " z"<<z<<" p-rx "<<p->rx()<<" p->ry"<<p->ry(); } glEnd(); } glEnable(GL_LIGHTING); glDisable(GL_LIGHTING); }
void PathPaintEngine::drawPath(const QPainterPath& path) { if (!dev) return; if(!isCosmetic) { QList<QPolygonF> polys = path.toSubpathPolygons(); for (int i = 0; i < polys.size(); ++i) { if(dashPattern.empty()) dev->addPath(transform.map(polys[i])); else { QPolygonF polytemp = transform.map(polys[i]), newpoly; int dashtoggle = 1, dashi=0, j = 0; qreal actualdashsize = dashPattern[dashi]; QPointF origin = QPointF(polytemp[j]), testp; j++; do { newpoly = QPolygonF(); newpoly.append(origin); do { testp = polytemp[j]; origin = QPointF(getPointAtLenght(QPointF(origin), polytemp[j], actualdashsize)); if (essentiallyEqual(origin.x(), polytemp[j].x(), 0.01 ) && approximatelyEqual(origin.y(), polytemp[j].y(),0.01) && j+1 < polytemp.size()) { origin = polytemp[j]; j++; testp = polytemp[j]; } newpoly.append(origin); }while(definitelyGreaterThan(actualdashsize,0.0,0.1) && testp!=origin); if(dashtoggle == 1) { dev->addPath(newpoly); } dashtoggle = dashtoggle * -1; dashi++; if(dashi >= dashPattern.size()) dashi=0; actualdashsize = dashPattern[dashi]; }while(!essentiallyEqual(origin.x(), polytemp[j].x(), 0.001 ) || !essentiallyEqual(origin.y(), polytemp[j].y(),0.001)); } } } }
QList<QPainterPath> splitDisjointPaths(const QPainterPath &path) { QList<QPainterPath> resultList; QList<QPolygonF> inputPolygons = path.toSubpathPolygons(); Q_FOREACH (const QPolygonF &poly, inputPolygons) { QPainterPath testPath; testPath.addPolygon(poly); if (resultList.isEmpty()) { resultList.append(testPath); continue; } QList<QPainterPath>::iterator it = resultList.begin(); QList<QPainterPath>::iterator end = resultList.end(); QList<QPainterPath>::iterator savedIt = end; bool wasMerged = false; while (it != end) { bool skipIncrement = false; if (it->intersects(testPath)) { if (savedIt == end) { it->addPath(testPath); savedIt = it; } else { savedIt->addPath(*it); it = resultList.erase(it); skipIncrement = true; } wasMerged = true; } if (!skipIncrement) { ++it; } } if (!wasMerged) { resultList.append(testPath); } }
void tst_QPolygon::makeEllipse() { // create an ellipse with R1 = R2 = R, i.e. a circle QPolygon pa; const int R = 50; // radius QPainterPath path; path.addEllipse(0, 0, 2*R, 2*R); pa = path.toSubpathPolygons().at(0).toPolygon(); int i; // make sure that all points are R+-1 away from the center bool err = FALSE; for (i = 1; i < pa.size(); i++) { QPoint p = pa.at( i ); double r = sqrt( pow( double(p.x() - R), 2.0 ) + pow( double(p.y() - R), 2.0 ) ); // ### too strict ? at least from visual inspection it looks // quite odd around the main axes. 2.0 passes easily. err |= ( qAbs( r - double(R) ) > 2.0 ); } QVERIFY( !err ); }
void PencilTool::smoothPath(QPainterPath &path, double smoothness, int from, int to) { QPolygonF polygon; QList<QPolygonF> polygons = path.toSubpathPolygons(); QList<QPolygonF>::iterator it = polygons.begin(); QPolygonF::iterator pointIt; while (it != polygons.end()) { pointIt = (*it).begin(); while (pointIt <= (*it).end()-2) { polygon << (*pointIt); pointIt += 2; } ++it; } if (smoothness > 0) { path = TupGraphicalAlgorithm::bezierFit(polygon, smoothness, from, to); } else { path = QPainterPath(); path.addPolygon(polygon); } }
/*! Sets the points of the array to those describing an ellipse with size, width \a w by height \a h, and position (\a x, \a y). The returned array has sufficient resolution for use as pixels. */ void Q3PointArray::makeEllipse(int x, int y, int w, int h) { QPainterPath path; path.addEllipse(x, y, w, h); *this = path.toSubpathPolygons().at(0).toPolygon(); }
/*! Draw the shape item \param painter Painter \param xMap X-Scale Map \param yMap Y-Scale Map \param canvasRect Contents rect of the plot canvas */ void QwtPlotShapeItem::draw( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect ) const { if ( d_data->shape.isEmpty() ) return; if ( d_data->pen.style() == Qt::NoPen && d_data->brush.style() == Qt::NoBrush ) { return; } const QRectF cRect = QwtScaleMap::invTransform( xMap, yMap, canvasRect.toRect() ); if ( d_data->boundingRect.intersects( cRect ) ) { const bool doAlign = QwtPainter::roundingAlignment( painter ); QPainterPath path = qwtTransformPath( xMap, yMap, d_data->shape, doAlign ); if ( testPaintAttribute( QwtPlotShapeItem::ClipPolygons ) ) { qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF()); QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw ); QPainterPath clippedPath; clippedPath.setFillRule( path.fillRule() ); const QList<QPolygonF> polygons = path.toSubpathPolygons(); for ( int i = 0; i < polygons.size(); i++ ) { const QPolygonF p = QwtClipper::clipPolygonF( clipRect, polygons[i], true ); clippedPath.addPolygon( p ); } path = clippedPath; } if ( d_data->renderTolerance > 0.0 ) { QwtWeedingCurveFitter fitter( d_data->renderTolerance ); QPainterPath fittedPath; fittedPath.setFillRule( path.fillRule() ); const QList<QPolygonF> polygons = path.toSubpathPolygons(); for ( int i = 0; i < polygons.size(); i++ ) fittedPath.addPolygon( fitter.fitCurve( polygons[ i ] ) ); path = fittedPath; } painter->setPen( d_data->pen ); painter->setBrush( d_data->brush ); painter->drawPath( path ); } }
QPolygonF curvedArrow( QPointF po, QPointF pm, QPointF pd, qreal startWidth, qreal width, qreal headSize, QgsArrowSymbolLayer::HeadType headType, qreal offset ) { qreal circleRadius; QPointF circleCenter; if ( ! pointsToCircle( po, pm, pd, circleCenter, circleRadius ) || circleRadius > 10000.0 ) { // aligned points => draw a straight arrow return straightArrow( po, pd, startWidth, width, headSize, headType, offset ); } // angles of each point qreal angle_o = clampAngle( atan2( circleCenter.y() - po.y(), po.x() - circleCenter.x() ) ); qreal angle_m = clampAngle( atan2( circleCenter.y() - pm.y(), pm.x() - circleCenter.x() ) ); qreal angle_d = clampAngle( atan2( circleCenter.y() - pd.y(), pd.x() - circleCenter.x() ) ); // arc direction : 1 = counter-clockwise, -1 = clockwise int direction = clampAngle( angle_m - angle_o ) < clampAngle( angle_m - angle_d ) ? 1 : -1; qreal deltaAngle = angle_d - angle_o; if ( direction * deltaAngle < 0.0 ) deltaAngle = deltaAngle + direction * 2 * M_PI; qreal length = euclidian_distance( po, pd ); // for close points and deltaAngle < 180, draw a straight line if ( fabs( deltaAngle ) < M_PI && ((( headType == QgsArrowSymbolLayer::HeadSingle ) && ( length < headSize ) ) || (( headType == QgsArrowSymbolLayer::HeadReversed ) && ( length < headSize ) ) || (( headType == QgsArrowSymbolLayer::HeadDouble ) && ( length < 2*headSize ) ) ) ) { return straightArrow( po, pd, startWidth, width, headSize, headType, offset ); } // ajust coordinates to include offset circleRadius += offset; po = circlePoint( circleCenter, circleRadius, angle_o ); pm = circlePoint( circleCenter, circleRadius, angle_m ); pd = circlePoint( circleCenter, circleRadius, angle_d ); qreal headAngle = direction * atan( headSize / circleRadius ); QPainterPath path; if ( headType == QgsArrowSymbolLayer::HeadDouble ) { // the first head path.moveTo( po ); path.lineTo( circlePoint( circleCenter, circleRadius + direction * headSize, angle_o + headAngle ) ); pathArcTo( path, circleCenter, circleRadius + direction * width / 2, angle_o + headAngle, angle_d - headAngle, direction ); // the second head path.lineTo( circlePoint( circleCenter, circleRadius + direction * headSize, angle_d - headAngle ) ); path.lineTo( pd ); path.lineTo( circlePoint( circleCenter, circleRadius - direction * headSize, angle_d - headAngle ) ); pathArcTo( path, circleCenter, circleRadius - direction * width / 2, angle_d - headAngle, angle_o + headAngle, -direction ); // the end of the first head path.lineTo( circlePoint( circleCenter, circleRadius - direction * headSize, angle_o + headAngle ) ); path.lineTo( po ); } else if ( headType == QgsArrowSymbolLayer::HeadSingle ) { path.moveTo( circlePoint( circleCenter, circleRadius + direction * startWidth / 2, angle_o ) ); spiralArcTo( path, circleCenter, angle_o, circleRadius + direction * startWidth / 2, angle_d - headAngle, circleRadius + direction * width / 2, direction ); // the arrow head path.lineTo( circlePoint( circleCenter, circleRadius + direction * headSize, angle_d - headAngle ) ); path.lineTo( pd ); path.lineTo( circlePoint( circleCenter, circleRadius - direction * headSize, angle_d - headAngle ) ); spiralArcTo( path, circleCenter, angle_d - headAngle, circleRadius - direction * width / 2, angle_o, circleRadius - direction * startWidth / 2, -direction ); path.lineTo( circlePoint( circleCenter, circleRadius + direction * startWidth / 2, angle_o ) ); } else if ( headType == QgsArrowSymbolLayer::HeadReversed ) { path.moveTo( circlePoint( circleCenter, circleRadius + direction * width / 2, angle_o + headAngle ) ); spiralArcTo( path, circleCenter, angle_o + headAngle, circleRadius + direction * width / 2, angle_d, circleRadius + direction * startWidth / 2, direction ); path.lineTo( circlePoint( circleCenter, circleRadius - direction * startWidth / 2, angle_d ) ); spiralArcTo( path, circleCenter, angle_d, circleRadius - direction * startWidth / 2, angle_o + headAngle, circleRadius - direction * width / 2, - direction ); path.lineTo( circlePoint( circleCenter, circleRadius - direction * headSize, angle_o + headAngle ) ); path.lineTo( po ); path.lineTo( circlePoint( circleCenter, circleRadius + direction * headSize, angle_o + headAngle ) ); path.lineTo( circlePoint( circleCenter, circleRadius + direction * width / 2, angle_o + headAngle ) ); } return path.toSubpathPolygons().at( 0 ); }
/*! Draw the shape item \param painter Painter \param xMap X-Scale Map \param yMap Y-Scale Map \param canvasRect Contents rect of the plot canvas */ void QwtPlotShapeItem::draw( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect ) const { if ( d_data->shape.isEmpty() ) return; if ( d_data->pen.style() == Qt::NoPen && d_data->brush.style() == Qt::NoBrush ) { return; } const QRectF cr = QwtScaleMap::invTransform( xMap, yMap, canvasRect.toRect() ); const QRectF &br = d_data->boundingRect; if ( ( br.left() > cr.right() ) || ( br.right() < cr.left() ) || ( br.top() > cr.bottom() ) || ( br.bottom() < cr.top() ) ) { // outside the visisble area return; } const bool doAlign = QwtPainter::roundingAlignment( painter ); QPainterPath path = qwtTransformPath( xMap, yMap, d_data->shape, doAlign ); if ( testPaintAttribute( QwtPlotShapeItem::ClipPolygons ) ) { const qreal pw = QwtPainter::effectivePenWidth( painter->pen() ); const QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw ); QPainterPath clippedPath; clippedPath.setFillRule( path.fillRule() ); QList<QPolygonF> polygons = path.toSubpathPolygons(); for ( int i = 0; i < polygons.size(); i++ ) { QwtClipper::clipPolygonF( clipRect, polygons[i], true ); clippedPath.addPolygon( polygons[i] ); } path = clippedPath; } if ( d_data->renderTolerance > 0.0 ) { QwtWeedingCurveFitter fitter( d_data->renderTolerance ); QPainterPath fittedPath; fittedPath.setFillRule( path.fillRule() ); const QList<QPolygonF> polygons = path.toSubpathPolygons(); for ( int i = 0; i < polygons.size(); i++ ) fittedPath.addPolygon( fitter.fitCurve( polygons[ i ] ) ); path = fittedPath; } painter->setPen( d_data->pen ); painter->setBrush( d_data->brush ); painter->drawPath( path ); }
void KisOpenGLCanvas2::paintToolOutline(const QPainterPath &path) { d->cursorShader->bind(); // setup the mvp transformation KisCoordinatesConverter *converter = coordinatesConverter(); QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(converter->flakeToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->cursorShader->setUniformValue(d->cursorShader->location(Uniform::ModelViewProjection), modelMatrix); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // XXX: glLogicOp not in ES 2.0 -- it would be better to use another method. // It is defined in 3.1 core profile onward. // Actually, https://www.opengl.org/sdk/docs/man/html/glLogicOp.xhtml says it's in 2.0 onwards, // only not in ES, but we don't care about ES, so we could use the function directly. glEnable(GL_COLOR_LOGIC_OP); if (ptr_glLogicOp) { ptr_glLogicOp(GL_XOR); } // Paint the tool outline if (KisOpenGL::hasOpenGL3()) { d->outlineVAO.bind(); d->lineBuffer.bind(); } // Convert every disjointed subpath to a polygon and draw that polygon QList<QPolygonF> subPathPolygons = path.toSubpathPolygons(); for (int i = 0; i < subPathPolygons.size(); i++) { const QPolygonF& polygon = subPathPolygons.at(i); QVector<QVector3D> vertices; vertices.resize(polygon.count()); for (int j = 0; j < polygon.count(); j++) { QPointF p = polygon.at(j); vertices[j].setX(p.x()); vertices[j].setY(p.y()); } if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.allocate(vertices.constData(), 3 * vertices.size() * sizeof(float)); } else { d->cursorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->cursorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, vertices.constData()); } glDrawArrays(GL_LINE_STRIP, 0, vertices.size()); } if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.release(); d->outlineVAO.release(); } glDisable(GL_COLOR_LOGIC_OP); d->cursorShader->release(); }
void GLText::initializeGlyph(char ch) { Glyph glyph; QPainterPath path; if(debugTesselation) printf("Adding glyph %c\n",ch); path.addText(0,0,font,QString((QChar)ch)); QList<QPolygonF> polygons = path.toSubpathPolygons(); if(debugTesselation){ printf("%d Sub-Polygons\n",polygons.size()); printf("Poly has %d vertices:\n",polygons.size()); } int numVertices = 0; double minX=DBL_MAX, minY=DBL_MAX, maxX=-DBL_MAX, maxY=-DBL_MAX; for(int i=0; i<polygons.size(); i++){ if(debugTesselation) printf("Sub-Polygon %d:\n",i); numVertices += polygons[i].size(); for(int k=0; k<polygons[i].size(); k++){ if(debugTesselation) printf("%8.3f,%8.3f\n",polygons[i][k].x(),polygons[i][k].y()); minX = min(minX, polygons[i][k].x()); maxX = max(maxX, polygons[i][k].x()); minY = min(minY, polygons[i][k].y()); maxY = max(maxY, polygons[i][k].y()); } } glyph.ascent = fabs(minY)/FontRenderSize; glyph.descent = fabs(maxY)/FontRenderSize; glyph.height = (maxY - minY)/FontRenderSize; glyph.width = (maxX - minX)/FontRenderSize; if(debugTesselation) printf("numVertices: %d\n",numVertices); GLdouble vertices[numVertices][3]; int j=0; for(int i=0; i<polygons.size(); i++){ for(int k=0; k<polygons[i].size(); k++){ vertices[j][0] = polygons[i][k].x()/FontRenderSize; vertices[j][1] = -polygons[i][k].y()/FontRenderSize; vertices[j][2] = 9; j++; } } GLUtesselator* tess = gluNewTess(); gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr) tessBeginCB); gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr) tessEndCB); gluTessCallback(tess, GLU_TESS_ERROR, (_GLUfuncptr) tessErrorCB); gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr) tessVertexCB); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glyph.displayListID = glGenLists(1); if(glyph.displayListID==GL_INVALID_VALUE){ printf("Unable to create display list!\n"); exit(1); } glNewList(glyph.displayListID, GL_COMPILE); gluTessBeginPolygon(tess, 0); j=0; for(int i=0; i<polygons.size(); i++){ gluTessBeginContour(tess); for(int k=0; k<polygons[i].size(); k++){ gluTessVertex(tess, vertices[j], vertices[j]); j++; } gluTessEndContour(tess); } gluTessEndPolygon(tess); gluDeleteTess(tess); glEndList(); glPopMatrix(); glyph.compiled = true; glyphs[ch] = glyph; }