void QgsMarkerLineSymbolLayerV2::renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { if ( points.size() > 0 ) { // calc length qreal length = 0; QPolygonF::const_iterator it = points.constBegin(); QPointF last = *it; for ( ++it; it != points.constEnd(); ++it ) { length += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) + ( last.y() - it->y() ) * ( last.y() - it->y() ) ); last = *it; } // find the segment where the central point lies it = points.constBegin(); last = *it; qreal last_at = 0, next_at = 0; QPointF next; int segment = 0; for ( ++it; it != points.constEnd(); ++it ) { next = *it; next_at += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) + ( last.y() - it->y() ) * ( last.y() - it->y() ) ); if ( next_at >= length / 2 ) break; // we have reached the center last = *it; last_at = next_at; segment++; } // find out the central point on segment MyLine l( last, next ); // for line angle qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at ); QPointF pt = last + ( next - last ) * k; // draw the marker double origAngle = mMarker->angle(); if ( mRotateMarker ) mMarker->setAngle( origAngle + l.angle() * 180 / M_PI ); mMarker->renderPoint( pt, context.feature(), context.renderContext(), -1, context.selected() ); if ( mRotateMarker ) mMarker->setAngle( origAngle ); } }
void QgsCoordinateTransform::transformPolygon( QPolygonF &poly, TransformDirection direction ) const { if ( !d->mIsValid || d->mShortCircuit ) { return; } //create x, y arrays int nVertices = poly.size(); QVector<double> x( nVertices ); QVector<double> y( nVertices ); QVector<double> z( nVertices ); double *destX = x.data(); double *destY = y.data(); double *destZ = z.data(); const QPointF *polyData = poly.constData(); for ( int i = 0; i < nVertices; ++i ) { *destX++ = polyData->x(); *destY++ = polyData->y(); *destZ++ = 0; polyData++; } try { transformCoords( nVertices, x.data(), y.data(), z.data(), direction ); } catch ( const QgsCsException & ) { // rethrow the exception QgsDebugMsg( QStringLiteral( "rethrowing exception" ) ); throw; } QPointF *destPoint = poly.data(); const double *srcX = x.constData(); const double *srcY = y.constData(); for ( int i = 0; i < nVertices; ++i ) { destPoint->rx() = *srcX++; destPoint->ry() = *srcY++; destPoint++; } }
/********************************************************************** * Function: get handle point * Parameters: handle id, bound rect * Return: none **********************************************************************/ QPointF QArcItem::getHandle(int iHandle, QRectF &qrcBondingRect) const { QPointF qpPoint; if (iHandle > 8) { QList<QPolygonF> polygonfs = m_ArcPath.toSubpathPolygons(); int iSize = polygonfs.size(); if (iSize <= 0 || iSize > 1) { return qpPoint; } QPolygonF polygonf = polygonfs.at(0); int j = polygonf.size(); if (j <= 1) { return qpPoint;; } /*Get the key points*/ QPointF qpDimCenter; qpDimCenter = polygonf.at(0); switch (iHandle) { case 9: qpPoint = polygonf.at(1); qpPoint.rx() = (qpPoint.x() + qpDimCenter.x()) / 2; qpPoint.ry() = (qpPoint.y() + qpDimCenter.y()) / 2; break; case 10: qpPoint = polygonf.at(j - 1); qpPoint.rx() = (qpPoint.x() + qpDimCenter.x()) / 2; qpPoint.ry() = (qpPoint.y() + qpDimCenter.y()) / 2; break; default: break; } qpPoint = this->mapToScene(qpPoint); qpPoint.rx() = qpPoint.x(); return qpPoint; } else { return SamDrawItemBase::getHandle(iHandle, qrcBondingRect); } }
void QgsSimpleLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } double offset = 0.0; applyDataDefinedSymbology( context, mPen, mSelPen, offset ); p->setPen( context.selected() ? mSelPen : mPen ); // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #2 points). if ( points.size() <= 2 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( context.renderContext(), QgsVectorLayer::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( points, context.layer()->simplifyMethod().threshold() ) && ( p->renderHints() & QPainter::Antialiasing ) ) { p->setRenderHint( QPainter::Antialiasing, false ); p->drawPolyline( points ); p->setRenderHint( QPainter::Antialiasing, true ); return; } if ( mDrawInsidePolygon ) { //only drawing the line on the interior of the polygon, so set clip path for painter p->save(); QPainterPath clipPath; clipPath.addPolygon( points ); p->setClipPath( clipPath, Qt::IntersectClip ); } if ( offset == 0 ) { p->drawPolyline( points ); } else { double scaledOffset = offset * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit ); p->drawPolyline( ::offsetLine( points, scaledOffset ) ); } if ( mDrawInsidePolygon ) { //restore painter to reset clip path p->restore(); } }
//! Sutherland-Hodgman polygon clipping QPolygonF GraphPolygonClipperF::clipPolygon(const QPolygonF &pa) const { if ( contains( ::boundingRect(pa) ) ) return pa; QPolygonF cpa(pa.size()); clipEdge((Edge)0, pa, cpa); for ( uint edge = 1; edge < NEdges; edge++ ) { const QPolygonF rpa = cpa; clipEdge((Edge)edge, rpa, cpa); } return cpa; }
void QgsFillSymbolLayerV2::_renderPolygon( QPainter* p, const QPolygonF& points, const QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) { if ( !p ) { return; } // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #5 points). if ( points.size() <= 5 && ( context.renderContext().vectorSimplifyMethod().simplifyHints() & QgsVectorSimplifyMethod::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::isGeneralizableByDeviceBoundingBox( points, context.renderContext().vectorSimplifyMethod().threshold() ) && ( p->renderHints() & QPainter::Antialiasing ) ) { p->setRenderHint( QPainter::Antialiasing, false ); p->drawRect( points.boundingRect() ); p->setRenderHint( QPainter::Antialiasing, true ); return; } // polygons outlines are sometimes rendered wrongly with drawPolygon, when // clipped (see #13343), so use drawPath instead. if ( !rings && p->pen().style() == Qt::NoPen ) { // simple polygon without holes p->drawPolygon( points ); } else { // polygon with holes must be drawn using painter path QPainterPath path; QPolygonF outerRing = points; path.addPolygon( outerRing ); if ( rings ) { QList<QPolygonF>::const_iterator it = rings->constBegin(); for ( ; it != rings->constEnd(); ++it ) { QPolygonF ring = *it; path.addPolygon( ring ); } } p->drawPath( path ); } }
QString ShortNavigation::buildWKTPolygon( const QPolygonF &rhomboid ) { QString WKTPolygon = "'POLYGON(("; for ( int i = 0; i < rhomboid.size(); i++ ) { WKTPolygon.append( QString::number( rhomboid[i].x(), 'f', WKT_P)); WKTPolygon.append( " "); WKTPolygon.append( QString::number( rhomboid[i].y(), 'f', WKT_P)); WKTPolygon.append( ","); } WKTPolygon.append( QString::number( rhomboid.at(0).x(), 'f', WKT_P)); WKTPolygon.append( " "); WKTPolygon.append( QString::number( rhomboid.at(0).y(), 'f', WKT_P)); WKTPolygon.append( "))'"); return WKTPolygon; }
static SplineStore qwtSplinePathG1( const QwtSplineCardinalG1 *spline, const QPolygonF &points ) { const int size = points.size(); const int numTensions = spline->isClosing() ? size : size - 1; const QVector<QwtSplineCardinalG1::Tension> tensions2 = spline->tensions( points ); if ( tensions2.size() != numTensions ) return SplineStore(); const QPointF *p = points.constData(); const QwtSplineCardinalG1::Tension *t = tensions2.constData(); SplineStore store; store.init( numTensions ); store.start( p[0] ); const QPointF &p0 = spline->isClosing() ? p[size-1] : p[0]; QPointF vec1 = ( p[1] - p0 ) * 0.5; for ( int i = 0; i < size - 2; i++ ) { const QPointF vec2 = ( p[i+2] - p[i] ) * 0.5; store.addCubic( p[i] + vec1 * t[i].t1, p[i+1] - vec2 * t[i].t2, p[i+1] ); vec1 = vec2; } const QPointF &pn = spline->isClosing() ? p[0] : p[size-1]; const QPointF vec2 = 0.5 * ( pn - p[size - 2] ); store.addCubic( p[size - 2] + vec1 * t[size-2].t1, p[size - 1] - vec2 * t[size-2].t2, p[size - 1] ); if ( spline->isClosing() ) { const QPointF vec3 = 0.5 * ( p[1] - p[size-1] ); store.addCubic( p[size-1] + vec2 * t[size-1].t1, p[0] - vec3 * t[size-1].t2, p[0] ); } return store; }
/*! \param points Series of data points \return Curve points */ QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const { QPolygonF fittedPoints; if ( d_data->chunkSize == 0 ) { fittedPoints = simplify( points ); } else { for ( int i = 0; i < points.size(); i += d_data->chunkSize ) { const QPolygonF p = points.mid( i, d_data->chunkSize ); fittedPoints += simplify( p ); } } return fittedPoints; }
bool LinearFunction::apply(const QPolygonF& curveSamples, float x, float& y) { const int nbSamples = curveSamples.size(); for (int i=0; i<nbSamples; ++i) { const QPointF& point1 = curveSamples[i]; if (i+1 < nbSamples) { const QPointF& point2 = curveSamples[i+1]; if (point1.x()!=point2.x() && x>=point1.x() && x<=point2.x()) { LinearFunction f(point1, point2); y = f(x); return true; } } } return false; }
QString QTikzPicturePrivate::toTikzPath(const QPolygonF & polygon) const { if (polygon.isEmpty()) return QString(); const int end = polygon.size() - polygon.isClosed() ? 1 : 0; QString path; for (int i = 0; i < end; ++i) { if (i == 0) { path = toCoord(polygon[i]); } else if (i == end - 1) { path += " -- cycle"; } else { path += " -- " + toCoord(polygon[i]); } } return path; }
// Check whether a point is on the border static bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) { QPointF p1 = border.at(0); QPointF p2; for (int i = 1; i < border.size(); ++i) { p2 = border.at(i); if (areCollinear(p, p1, p2) // Once we know that the points are collinear we // only need to check one of the coordinates && (qAbs(p2.x() - p1.x()) > qAbs(p2.y() - p1.y()) ? withinRange(p.x(), p1.x(), p2.x()) : withinRange(p.y(), p1.y(), p2.y()))) { return true; } p1 = p2; } return false; }
void QgsSimpleLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { QPainter* p = context.renderContext().painter(); if ( !p ) { return; } //size scaling by field if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) { applySizeScale( context, mPen, mSelPen ); } double offset = mOffset; applyDataDefinedSymbology( context, mPen, mSelPen, offset ); p->setPen( context.selected() ? mSelPen : mPen ); // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #2 points). if ( points.size() <= 2 && ( context.renderContext().vectorSimplifyMethod().simplifyHints() & QgsVectorSimplifyMethod::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::isGeneralizableByDeviceBoundingBox( points, context.renderContext().vectorSimplifyMethod().threshold() ) && ( p->renderHints() & QPainter::Antialiasing ) ) { p->setRenderHint( QPainter::Antialiasing, false ); p->drawPolyline( points ); p->setRenderHint( QPainter::Antialiasing, true ); return; } if ( qgsDoubleNear( offset, 0 ) ) { p->drawPolyline( points ); } else { double scaledOffset = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), offset, mOffsetUnit, mOffsetMapUnitScale ); QList<QPolygonF> mline = ::offsetLine( points, scaledOffset, context.feature() ? context.feature()->constGeometry()->type() : QGis::Line ); for ( int part = 0; part < mline.count(); ++part ) p->drawPolyline( mline[ part ] ); } }
/*! \brief Complete a polygon to be a closed polygon including the area between the original polygon and the baseline. \param painter Painter \param xMap X map \param yMap Y map \param polygon Polygon to be completed */ void QwtPlotCurve::closePolyline( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, QPolygonF &polygon ) const { if ( polygon.size() < 2 ) return; const bool doAlign = QwtPainter::roundingAlignment( painter ); double baseline = d_data->baseline; if ( orientation() == Qt::Vertical ) { if ( yMap.transformation()->type() == QwtScaleTransformation::Log10 ) { if ( baseline < QwtScaleMap::LogMin ) baseline = QwtScaleMap::LogMin; } double refY = yMap.transform( baseline ); if ( doAlign ) refY = qRound( refY ); polygon += QPointF( polygon.last().x(), refY ); polygon += QPointF( polygon.first().x(), refY ); } else { if ( xMap.transformation()->type() == QwtScaleTransformation::Log10 ) { if ( baseline < QwtScaleMap::LogMin ) baseline = QwtScaleMap::LogMin; } double refX = xMap.transform( baseline ); if ( doAlign ) refX = qRound( refX ); polygon += QPointF( refX, polygon.last().y() ); polygon += QPointF( refX, polygon.first().y() ); } }
QPolygonF Shape::vertices() const { QPolygonF result = vertices_; switch (type_) { case SEGMENT: case POLYLINE: case CLOSED_POLYLINE: case POLYGON: break; case RECTANGLE: if (result.size() == 2) { result = QPolygonF(QRectF(result[0], result[1])); result.pop_back(); } break; } return result; }
bool PathPlanner::pointInPolygon(const QPointF &point, const QPolygonF &polygon) { int polyCorners = polygon.size(); int i, j = polyCorners - 1; bool oddNodes = false; double x = point.x(), y = point.y(); for (i=0; i < polyCorners; i++) { if ( ((polygon[i].y() < y && polygon[j].y() >= y) || (polygon[j].y() < y && polygon[i].y() >= y)) && (polygon[i].x() <= x || polygon[j].x()<=x)) { oddNodes ^= (polygon[i].x()+(y-polygon[i].y())/(polygon[j].y()-polygon[i].y())*(polygon[j].x()-polygon[i].x())<x); } j = i; } return oddNodes; }
void EditPolygonTool::deleteNodes() { if (mSelectedHandles.isEmpty()) return; PointIndexesByObject p = groupIndexesByObject(mSelectedHandles); QMapIterator<MapObject*, RangeSet<int> > i(p); QUndoStack *undoStack = mapDocument()->undoStack(); QString delText = tr("Delete %n Node(s)", "", mSelectedHandles.size()); undoStack->beginMacro(delText); while (i.hasNext()) { MapObject *object = i.next().key(); const RangeSet<int> &indexRanges = i.value(); QPolygonF oldPolygon = object->polygon(); QPolygonF newPolygon = oldPolygon; // Remove points, back to front to keep the indexes valid RangeSet<int>::Range it = indexRanges.end(); RangeSet<int>::Range begin = indexRanges.begin(); // assert: end != begin, since there is at least one entry do { --it; newPolygon.remove(it.first(), it.length()); } while (it != begin); if (newPolygon.size() < 2) { // We've removed the entire object undoStack->push(new RemoveMapObject(mapDocument(), object)); } else { undoStack->push(new ChangePolygon(mapDocument(), object, newPolygon, oldPolygon)); } } undoStack->endMacro(); }
QPainterPath QwtSplinePleasing::pathP( const QPolygonF &points ) const { const int size = points.size(); if ( size <= 2 ) return QwtSplineCardinalG1::pathP( points ); using namespace QwtSplineCardinalG1P; PathStore store; switch( parametrization()->type() ) { case QwtSplineParameter::ParameterX: { store = qwtSplinePathPleasing<PathStore>( points, isClosing(), QwtSplineParameter::paramX() ); break; } case QwtSplineParameter::ParameterUniform: { store = qwtSplinePathPleasing<PathStore>( points, isClosing(), QwtSplineParameter::paramUniform() ); break; } case QwtSplineParameter::ParameterChordal: { store = qwtSplinePathPleasing<PathStore>( points, isClosing(), QwtSplineParameter::paramChordal() ); break; } default: { store = qwtSplinePathPleasing<PathStore>( points, isClosing(), QwtSplineParameter::param( parametrization() ) ); } } if ( isClosing() ) store.path.closeSubpath(); return store.path; }
QPolygonF polygonFromPath(potrace_path_t *path, int bezierPrecision) { QPolygonF poly; if(!path) return poly; int n = path->curve.n; int *tag = path->curve.tag; potrace_dpoint_t (*c)[3] = path->curve.c; for(int i = 0; i < n; ++i) { switch (tag[i]) { case POTRACE_CORNER: poly << QPointF(c[i][1].x, c[i][1].y) << QPointF(c[i][2].x, c[i][2].y); break; case POTRACE_CURVETO: { QPointF pa, pb, pc, pd; pa = poly.isEmpty()? QPointF(c[n-1][2].x, c[n-1][2].y) : poly.last(); pb = QPointF(c[i][0].x, c[i][0].y); pc = QPointF(c[i][1].x, c[i][1].y); pd = QPointF(c[i][2].x, c[i][2].y); for(int i = 1; i <= bezierPrecision; ++i) { poly << bezier(pa, pb, pc, pd, static_cast<qreal>(i)/bezierPrecision); } } break; } } if(!poly.isEmpty() && poly.first() == poly.last()) { poly.remove(poly.size()-1); } return poly; }
QPainterPath OrthogonalRenderer::shape(const MapObject *object) const { QPainterPath path; if (object->tile()) { path.addRect(boundingRect(object)); } else { switch (object->shape()) { case MapObject::Rectangle: { const QRectF bounds = object->bounds(); const QRectF rect(tileToPixelCoords(bounds.topLeft()), tileToPixelCoords(bounds.bottomRight())); if (rect.isNull()) { path.addEllipse(rect.topLeft(), 20, 20); } else { path.addRoundedRect(rect, 10, 10); } break; } case MapObject::Polygon: case MapObject::Polyline: { const QPointF &pos = object->position(); const QPolygonF polygon = object->polygon().translated(pos); const QPolygonF screenPolygon = tileToPixelCoords(polygon); if (object->shape() == MapObject::Polygon) { path.addPolygon(screenPolygon); } else { for (int i = 1; i < screenPolygon.size(); ++i) { path.addPolygon(lineToPolygon(screenPolygon[i - 1], screenPolygon[i])); } path.setFillRule(Qt::WindingFill); } break; } } } return path; }
static inline QVector<QwtSplineCardinalG1::Tension> qwtTensions( const QPolygonF &points, bool isClosed, Param param ) { const int size = points.size(); QVector<QwtSplineCardinalG1::Tension> tensions2( isClosed ? size : size - 1 ); const QPointF *p = points.constData(); QwtSplineCardinalG1::Tension *t = tensions2.data(); const QPointF &p0 = isClosed ? p[size-1] : p[0]; double d13 = param(p[0], p[2]); t[0] = qwtTension( param(p0, p[1]), param(p[0], p[1]), d13, p0, p[0], p[1], p[2] ); for ( int i = 1; i < size - 2; i++ ) { const double d23 = param( p[i], p[i+1] ); const double d24 = param( p[i], p[i+2] ); t[i] = qwtTension( d13, d23, d24, p[i-1], p[i], p[i+1], p[i+2] ); d13 = d24; } const QPointF &pn = isClosed ? p[0] : p[size-1]; const double d24 = param( p[size-2], pn ); t[size-2] = qwtTension( d13, param( p[size-2], p[size-1] ), d24, p[size - 3], p[size - 2], p[size - 1], pn ); if ( isClosed ) { const double d34 = param( p[size-1], p[0] ); const double d35 = param( p[size-1], p[1] ); t[size-1] = qwtTension( d24, d34, d35, p[size-2], p[size-1], p[0], p[1] ); } return tensions2; }
void Renderer::drawMesh() { // render mesh as a wireframe QPainter p(&mImage); p.setRenderHint(QPainter::Antialiasing); p.setPen(QPen(QBrush(mCfg.mesh.mMeshColor),0.5)); p.setFont(QFont("")); const Mesh::Elements& elems = mMesh->elements(); for (int i=0; i < elems.count(); ++i) { const Element& elem = elems[i]; if( elem.isDummy() ) continue; // If the element is outside the view of the canvas, skip it if( elemOutsideView(i) ) continue; QPolygonF pts = elementPolygonPixel(elem); p.drawPolyline(pts.constData(), pts.size()); if (mCfg.mesh.mRenderMeshLabels) { double cx, cy; mMesh->elementCentroid(i, cx, cy); QString txt = QString::number(elem.id()); QRect bb = p.fontMetrics().boundingRect(txt); QPointF xy = mtp.realToPixel(cx, cy); bb.moveTo(xy.x() - bb.width()/2.0, xy.y() - bb.height()/2.0); if (pts.containsPoint(bb.bottomLeft(), Qt::WindingFill) && pts.containsPoint(bb.bottomRight(), Qt::WindingFill) && pts.containsPoint(bb.topLeft(), Qt::WindingFill) && pts.containsPoint(bb.topRight(), Qt::WindingFill)) { p.drawText(bb, Qt::AlignCenter, txt); } } } }
QPolygonF Shape::polygon() const { QPolygonF result = vertices_; switch (type_) { case SEGMENT: case POLYLINE: break; case CLOSED_POLYLINE: case POLYGON: result.append(result.first()); break; case RECTANGLE: if (result.size() == 2) result = QPolygonF(QRectF(result[0], result[1])); break; } return result; }
void QgsCoordinateTransform::transformPolygon( QPolygonF& poly, TransformDirection direction ) const { if ( mShortCircuit || !mInitialisedFlag ) { return; } //create x, y arrays int nVertices = poly.size(); QVector<double> x( nVertices ); QVector<double> y( nVertices ); QVector<double> z( nVertices ); for ( int i = 0; i < nVertices; ++i ) { const QPointF& pt = poly.at( i ); x[i] = pt.x(); y[i] = pt.y(); z[i] = 0; } try { transformCoords( nVertices, x.data(), y.data(), z.data(), direction ); } catch ( const QgsCsException & ) { // rethrow the exception QgsDebugMsg( "rethrowing exception" ); throw; } for ( int i = 0; i < nVertices; ++i ) { QPointF& pt = poly[i]; pt.rx() = x[i]; pt.ry() = y[i]; } }
// ============================================================================ /// Checks if polygon is convex. bool isPolygonConvex( const QPolygonF& p ) { int points = p.size(); if ( points < 3 ) { return true; // short circuit edge case } int negatives = 0; int positives = 0; for( int i = 0; i < points; i++ ) { QPointF p1 = p[i]; QPointF p2 = p[(i+1)%points]; QPointF p3 = p[(i+2)%points]; // TODO use b2Cross here // converts these points to 2 3d vectors double a1 = p2.x() - p1.x(); double a2 = p2.y() - p1.y(); // a3 = 0 double b1 = p3.x() - p2.x(); double b2 = p3.y() - p2.y(); // b3 = 0; // now find cross product of these vectors // c = a x b // c1 = 0, c2 = 0 double c3 = a1*b2 - a2*b1; if ( c3 < 0 ) negatives ++; else positives++; } return ( negatives == 0 ) || ( positives == 0 ); }
void testDuplicates() { QwtSplineLocal spline( QwtSplineLocal::Cardinal ); spline.setParametrization( QwtSplineParametrization::ParameterChordal ); QPolygonF points; points += QPointF( 1, 6 ); points += QPointF( 2, 7 ); points += QPointF( 3, 5); points += QPointF( 2, 4 ); points += QPointF( 0, 3 ); // inserting duplicates QPolygonF points1; for ( int i = 0; i < points.size(); i++ ) { points1 += points[i]; points1 += points[i]; } testPaths( "Duplicates", spline, points, points1 ); spline.setBoundaryType( QwtSpline::ClosedPolygon ); testPaths( "Duplicates", spline, points, points1 ); QPolygonF points2 = points; points2.append( points[0] ); testPaths( "First point also at End", spline, points, points2 ); QPolygonF points3 = points; points3.prepend( points.first() ); testPaths( "First point twice", spline, points, points3 ); QPolygonF points4 = points; points4.append( points.last() ); testPaths( "Last point twice", spline, points, points4 ); }
void LineDiagram::Private::paintPolyline( PaintContext* ctx, const QBrush& brush, const QPen& pen, const QPolygonF& points ) const { ctx->painter()->setBrush( brush ); ctx->painter()->setPen( PrintingParameters::scalePen( QPen( pen.color(), pen.width(), pen.style(), Qt::FlatCap, Qt::MiterJoin ) ) ); #if QT_VERSION > 0x040299 ctx->painter()->drawPolyline( points ); #else // FIXME (Mirko) verify, this sounds reverse-logical // For Qt versions older than 4.3 drawPolyline is VERY slow // so we use traditional line segments drawing instead then. for (int i = 0; i < points.size()-1; ++i) ctx->painter()->drawLine( points.at(i), points.at(i+1) ); #endif }
QPainterPath QwtSpline::pathP( const QPolygonF &points ) const { const int n = points.size(); QPainterPath path; if ( n == 0 ) return path; if ( n == 1 ) { path.moveTo( points[0] ); return path; } if ( n == 2 ) { path.addPolygon( points ); return path; } const QVector<QLineF> controlPoints = bezierControlPointsP( points ); if ( controlPoints.size() < n - 1 ) return path; const QPointF *p = points.constData(); const QLineF *l = controlPoints.constData(); path.moveTo( p[0] ); for ( int i = 0; i < n - 1; i++ ) path.cubicTo( l[i].p1(), l[i].p2(), p[i+1] ); if ( controlPoints.size() >= n ) { path.cubicTo( l[n-1].p1(), l[n-1].p2(), p[0] ); path.closeSubpath(); } return path; }
// Check whether a point is on the border bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) { QPointF p1 = border.at(0); QPointF p2; for (int i = 1; i < border.size(); ++i) { p2 = border.at(i); // (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) && (y2-y1)(x-x1) == (y-y1)(x2-x1) // In which, (y2-y1)(x-x1) == (y-y1)(x2-x1) is from (y2-y1)/(x2-x1) == (y-y1)/(x-x1) // it want to check the slope between p1 and p2 is same with slope between p and p1, // if so then the three points lie on the same line. // In which, (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) want to make sure p is // between p1 and p2, not outside. if (((p.x() <= p1.x() && p.x() >= p2.x()) || (p.x() >= p1.x() && p.x() <= p2.x())) && ((p.y() <= p1.y() && p.y() >= p2.y()) || (p.y() >= p1.y() && p.y() <= p2.y())) && (p2.y() - p1.y()) * (p.x() - p1.x()) == (p.y() - p1.y()) * (p2.x() - p1.x())) { return true; } p1 = p2; } return false; }
void GraphPolygonClipperF::clipEdge(Edge edge, const QPolygonF &pa, QPolygonF &cpa) const { if ( pa.count() == 0 ) { cpa.resize(0); return; } unsigned int count = 0; GraphDoublePoint p1 = pa[0]; if ( insideEdge(p1, edge) ) addPoint(cpa, count++, p1); const uint nPoints = pa.size(); for ( uint i = 1; i < nPoints; i++ ) { const GraphDoublePoint p2 = pa[(int)i]; if ( insideEdge(p2, edge) ) { if ( insideEdge(p1, edge) ) addPoint(cpa, count++, p2); else { addPoint(cpa, count++, intersectEdge(p1, p2, edge)); addPoint(cpa, count++, p2); } } else { if ( insideEdge(p1, edge) ) addPoint(cpa, count++, intersectEdge(p1, p2, edge)); } p1 = p2; } cpa.resize(count); }