QPointF Meshing::addMiddlePoint(int id) { QPointF point(0,0); QPolygonF poly = mesh_.at(id); if(poly.isEmpty()) return point; if(!poly.isClosed()) poly << poly.at(0); mesh_.removeAt(id); for(int i=0;i<poly.size()-1;i++) point += poly.at(i); point /= (double)(poly.size()-1); /*while(!poly.containsPoint(point,Qt::WindingFill)){ point += QPointF(-50+rand()%100,-50+rand()%100); }*/ for(int i=0;i<poly.size()-1;i++){ QPolygonF p; p << poly.at(i) << poly.at(i+1) << point << poly.at(i); mesh_.push_back(p); } return point; }
static void ENP_centroid( const QPolygonF &pX, double &cx, double &cy ) { // http://stackoverflow.com/questions/2792443/finding-the-centroid-of-a-polygon/2792459#2792459 cx = 0; cy = 0; if ( pX.isEmpty() ) return; double signedArea = 0.0; // For all vertices except last int i = 0; for ( ; i < pX.size() - 1; ++i ) { ENP_centroid_step( pX, cx, cy, signedArea, i, i + 1 ); } // Do last vertex separately to avoid performing an expensive // modulus operation in each iteration. ENP_centroid_step( pX, cx, cy, signedArea, i, 0 ); signedArea *= 0.5; cx /= ( 6.0 * signedArea ); cy /= ( 6.0 * signedArea ); }
void TableTitleView::resizeTitle(float width, float height) { QPolygonF pol; pol=box->polygon(); if(pol.isEmpty()) { pol.append(QPointF(0.0f,0.0f)); pol.append(QPointF(1.0f,0.0f)); pol.append(QPointF(1.0f,1.0f)); pol.append(QPointF(0.0f,1.0f)); } this->resizePolygon(pol, width, height); box->setPolygon(pol); if(schema_name->text()==" ") obj_name->setPos((box->boundingRect().width() - obj_name->boundingRect().width())/2.0f, VERT_SPACING); else { schema_name->setPos((box->boundingRect().width() - (schema_name->boundingRect().width() + obj_name->boundingRect().width()))/2.0f, VERT_SPACING); obj_name->setPos(schema_name->pos().x() + schema_name->boundingRect().width(), VERT_SPACING); obj_name->setPos(schema_name->pos().x() + schema_name->boundingRect().width(), VERT_SPACING); } this->bounding_rect.setTopLeft(this->pos()); this->bounding_rect.setSize(QSizeF(box->boundingRect().width(), box->boundingRect().height())); }
void DiveCalculatedCeiling::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { // We don't have enougth data to calculate things, quit. if (!shouldCalculateStuff(topLeft, bottomRight)) return; AbstractProfilePolygonItem::modelDataChanged(topLeft, bottomRight); // Add 2 points to close the polygon. QPolygonF poly = polygon(); if (poly.isEmpty()) return; QPointF p1 = poly.first(); QPointF p2 = poly.last(); poly.prepend(QPointF(p1.x(), vAxis->posAtValue(0))); poly.append(QPointF(p2.x(), vAxis->posAtValue(0))); setPolygon(poly); QLinearGradient pat(0, polygon().boundingRect().top(), 0, polygon().boundingRect().bottom()); pat.setColorAt(0, getColor(CALC_CEILING_SHALLOW)); pat.setColorAt(1, getColor(CALC_CEILING_DEEP)); setPen(QPen(QBrush(Qt::NoBrush), 0)); setBrush(pat); gradientFactor->setX(poly.boundingRect().width() / 2 + poly.boundingRect().x()); DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); if (plannerModel->isPlanner()) { struct diveplan &diveplan = plannerModel->getDiveplan(); gradientFactor->setText(QString("GF %1/%2").arg(diveplan.gflow).arg(diveplan.gfhigh)); } else { gradientFactor->setText(QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh)); } }
void QgsMarkerLineSymbolLayerV2::renderOffsetVertexAlongLine( const QPolygonF &points, int vertex, double distance, QgsSymbolV2RenderContext& context ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); if ( distance == 0 ) { // rotate marker (if desired) if ( mRotateMarker ) { bool isRing = false; if ( points.first() == points.last() ) isRing = true; double angle = markerAngle( points, isRing, vertex ); mMarker->setAngle( origAngle + angle * 180 / M_PI ); } mMarker->renderPoint( points[vertex], context.feature(), rc, -1, context.selected() ); return; } int pointIncrement = distance > 0 ? 1 : -1; QPointF previousPoint = points[vertex]; int startPoint = distance > 0 ? qMin( vertex + 1, points.count() - 1 ) : qMax( vertex - 1, 0 ); int endPoint = distance > 0 ? points.count() - 1 : 0; double distanceLeft = qAbs( distance ); for ( int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement ) { const QPointF& pt = points[i]; if ( previousPoint == pt ) // must not be equal! continue; // create line segment MyLine l( previousPoint, pt ); if ( distanceLeft < l.length() ) { //destination point is in current segment QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft ); // rotate marker (if desired) if ( mRotateMarker ) { mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) ); } mMarker->renderPoint( markerPoint, context.feature(), rc, -1, context.selected() ); return; } distanceLeft -= l.length(); previousPoint = pt; } //didn't find point return; }
void testShapedGradientPainterImpl(const QPolygonF &selectionPolygon, const QString &testName, const QPolygonF &selectionErasePolygon = QPolygonF()) { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KisPaintDeviceSP dev = new KisPaintDevice(cs); QRect imageRect(0,0,300,300); KisSelectionSP selection = new KisSelection(); KisPixelSelectionSP pixelSelection = selection->pixelSelection(); KisPainter selPainter(pixelSelection); selPainter.setFillStyle(KisPainter::FillStyleForegroundColor); selPainter.setPaintColor(KoColor(Qt::white, pixelSelection->colorSpace())); selPainter.paintPolygon(selectionPolygon); if (!selectionErasePolygon.isEmpty()) { selPainter.setCompositeOp(COMPOSITE_ERASE); selPainter.setPaintColor(KoColor(Qt::white, pixelSelection->colorSpace())); selPainter.paintPolygon(selectionErasePolygon); } selPainter.end(); pixelSelection->invalidateOutlineCache(); pixelSelection->convertToQImage(0, imageRect).save("sgt_selection.png"); QLinearGradient testGradient; testGradient.setColorAt(0.0, Qt::white); testGradient.setColorAt(0.5, Qt::green); testGradient.setColorAt(1.0, Qt::black); testGradient.setSpread(QGradient::ReflectSpread); QScopedPointer<KoStopGradient> gradient( KoStopGradient::fromQGradient(&testGradient)); KisGradientPainter gc(dev, selection); gc.setGradient(gradient.data()); gc.setGradientShape(KisGradientPainter::GradientShapePolygonal); gc.paintGradient(selectionPolygon.boundingRect().topLeft(), selectionPolygon.boundingRect().bottomRight(), KisGradientPainter::GradientRepeatNone, 0, false, imageRect.x(), imageRect.y(), imageRect.width(), imageRect.height()); QVERIFY(TestUtil::checkQImageExternal(dev->convertToQImage(0, imageRect), "shaped_gradient", "fill", testName, 1, 1, 0)); }
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; }
void LineWidthItem::paintContents(QPainter *p) { static QPolygonF pp; if (pp.isEmpty()) for (double x=10; x<22.1; x+=0.5) pp << QPointF(x, 16-(x-16)-sin(.7*(x-12))); p->setPen(QPen(c, lw)); p->setBrush(Qt::NoBrush); if (straight) p->drawLine(QLineF(QPointF(10, 22), QPointF(22, 10))); else p->drawPolyline(pp); }
/** * @brief Function to show the plot * * @param _plot * @param _residualVO * @param _points * @return QPolygonF */ QPolygonF ResidualTabHelper::showPlot(QwtPlot * _plot, SolverResidualVO * _residualVO, QPolygonF _points) { if (_points.isEmpty()) _points << QPointF(0,0) ; int _iteration = _residualVO->getIteration(); _points << QPointF(50+_iteration,100+_iteration ); _curve->setSamples(_points); _curve->attach(_plot ); _plot->replot(); _plot->show(); return _points; }
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); int i, maxCount; bool isRing = false; if ( placement == FirstVertex ) { i = 0; maxCount = 1; } else if ( placement == LastVertex ) { i = points.count() - 1; maxCount = points.count(); } else { i = 0; maxCount = points.count(); if ( points.first() == points.last() ) isRing = true; } for ( ; i < maxCount; ++i ) { if ( isRing && placement == Vertex && i == points.count() - 1 ) { continue; // don't draw the last marker - it has been drawn already } // rotate marker (if desired) if ( mRotateMarker ) { double angle = markerAngle( points, isRing, i ); mMarker->setAngle( origAngle + angle * 180 / M_PI ); } mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() ); } // restore original rotation mMarker->setAngle( origAngle ); }
void TestConnection::testRouteSimple() { MockCanvas canvas; KShapeManager manager(&canvas); KShape shape1; shape1.setPosition(30, 50); shape1.setSize(100, 200); manager.addShape(&shape1); KShapeConnection connection; connection.setStartPoint(&shape1, 0); connection.setEndPoint(150, 300); QPolygonF path = manager.routeConnection(&connection); QVERIFY(!path.isEmpty()); // TODO need to start at start and end at end }
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; }
/** * Extends or shrinks a line segment in such a way that if you draw perpendicular * lines through its endpoints, the given polygon would be squeezed between these * two perpendiculars. This ensures that the resulting line segment intersects * all the polygon edges it can possibly intersect. */ QLineF PageLayout::extendToCover(QLineF const& line, QPolygonF const& poly) { if (poly.isEmpty()) { return line; } // Project every vertex of the polygon onto the line and take extremas. double min = NumericTraits<double>::max(); double max = NumericTraits<double>::min(); ToLineProjector const projector(line); BOOST_FOREACH(QPointF const& pt, poly) { double const scalar = projector.projectionScalar(pt); if (scalar < min) { min = scalar; } if (scalar > max) { max = scalar; } }
// Check whether a point is on the border static bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) { // null border doesn't contain points if (border.isEmpty()) return false; 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; }
static QList<QPolygonF> splitToPolygons(const QList<QPointF> &line) { QList<QPolygonF> results; QPolygonF polygon; foreach (const QPointF &pt, line) { // if (!QIG::isNullValue(pt.y())) // y为时间轴或者深度轴 // { // polygon.append(pt); // } // else if (!polygon.isEmpty()) // { // results.append(polygon); // polygon.clear(); // } } if (!polygon.isEmpty()) { results.append(polygon); } return results; }
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); double angle; int i, maxCount; bool isRing = false; if ( placement == FirstVertex ) { i = 0; maxCount = 1; } else if ( placement == LastVertex ) { i = points.count() - 1; maxCount = points.count(); } else { i = 0; maxCount = points.count(); if ( points.first() == points.last() ) isRing = true; } for ( ; i < maxCount; ++i ) { const QPointF& pt = points[i]; // rotate marker (if desired) if ( mRotateMarker ) { if ( i == 0 ) { if ( !isRing ) { // use first segment's angle const QPointF& nextPt = points[i+1]; if ( pt == nextPt ) continue; angle = MyLine( pt, nextPt ).angle(); } else { // closed ring: use average angle between first and last segment const QPointF& prevPt = points[points.count() - 2]; const QPointF& nextPt = points[1]; if ( prevPt == pt || nextPt == pt ) continue; angle = _averageAngle( prevPt, pt, nextPt ); } } else if ( i == points.count() - 1 ) { if ( !isRing ) { // use last segment's angle const QPointF& prevPt = points[i-1]; if ( pt == prevPt ) continue; angle = MyLine( prevPt, pt ).angle(); } else { // don't draw the last marker - it has been drawn already continue; } } else { // use average angle const QPointF& prevPt = points[i-1]; const QPointF& nextPt = points[i+1]; if ( prevPt == pt || nextPt == pt ) continue; angle = _averageAngle( prevPt, pt, nextPt ); } mMarker->setAngle( origAngle + angle * 180 / M_PI ); } mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() ); } // restore original rotation mMarker->setAngle( origAngle ); }
void ClipPainterPrivate::clipPolyObject ( const QPolygonF & polygon, QVector<QPolygonF> & clippedPolyObjects, bool isClosed ) { // mDebug() << "ClipPainter enabled." ; // Only create a new polyObject as soon as we know for sure that // the current point is on the screen. QPolygonF clippedPolyObject = QPolygonF(); const QVector<QPointF>::const_iterator itStartPoint = polygon.constBegin(); const QVector<QPointF>::const_iterator itEndPoint = polygon.constEnd(); QVector<QPointF>::const_iterator itPoint = itStartPoint; // We use a while loop to be able to cover linestrings as well as linear rings: // Linear rings require to tessellate the path from the last node to the first node // which isn't really convenient to achieve with a for loop ... bool processingLastNode = false; while ( itPoint != itEndPoint ) { m_currentPoint = (*itPoint); // mDebug() << "m_currentPoint.x()" << m_currentPoint.x() << "m_currentPOint.y()" << m_currentPoint.y(); // Figure out the sector of the current point. m_currentSector = sector( m_currentPoint ); // Initialize the variables related to the previous point. if ( itPoint == itStartPoint && processingLastNode == false ) { if ( isClosed ) { m_previousPoint = polygon.last(); // Figure out the sector of the previous point. m_previousSector = sector( m_previousPoint ); } else { m_previousSector = m_currentSector; } } // If the current point reaches a new sector, take care of clipping. if ( m_currentSector != m_previousSector ) { if ( m_currentSector == 4 || m_previousSector == 4 ) { // In this case the current or the previous point is visible on the // screen but not both. Hence we only need to clip once and require // only one interpolation for both cases. clipOnce( clippedPolyObject, clippedPolyObjects, isClosed ); } else { // This case mostly deals with lines that reach from one // sector that is located off screen to another one that // is located off screen. In this situation the line // can get clipped once, twice, or not at all. clipMultiple( clippedPolyObject, clippedPolyObjects, isClosed ); } m_previousSector = m_currentSector; } // If the current point is onscreen, just add it to our final polygon. if ( m_currentSector == 4 ) { clippedPolyObject << m_currentPoint; #ifdef MARBLE_DEBUG ++(m_debugNodeCount); #endif } m_previousPoint = m_currentPoint; // Now let's handle the case where we have a (closed) polygon and where the // last point of the polyline is outside the viewport and the start point // is inside the viewport. This needs special treatment if ( processingLastNode ) { break; } ++itPoint; if ( itPoint == itEndPoint && isClosed ) { itPoint = itStartPoint; processingLastNode = true; } } // Only add the pointer if there's node data available. if ( !clippedPolyObject.isEmpty() ) { clippedPolyObjects << clippedPolyObject; } }
void Meshing::splitDiag() { for(int id=0;id<mesh_.size();id++){ QPolygonF poly = mesh_.at(id); if(poly.isEmpty()) continue; if(!poly.isClosed()) poly << poly.at(0); if(poly.size()<=4) continue; QStringList polyID; for(int k=0;k<poly.size();k++) polyID << findID(poly.at(k)); /*for(int i=0;i<poly.size()-2;i++){ QPointF p = (poly.at(i) + poly.at(i+2))/2.0; if(poly.containsPoint(p,Qt::WindingFill)){ QPolygonF p1,p2; for(int k=i;k<i+3;k++){ p1 << poly.at(k); } p1 << poly.at(i); for(int k=i+3;k<=poly.size()-1;k++){ p2 << poly.at(k); } for(int k=0;k<i;k++){ p2 << poly.at(k); } p2 << poly.at(i); mesh_.push_back(p1); mesh_.push_back(p2); mesh_.removeAt(id); splitDiag(); return; } }*/ //qDebug() << "Split poly" << polyID; for(int i=0;i<poly.size()-1;i++){ for(int j=i+2;j<poly.size()-(i==0?2:1);j++){ //qDebug() << "Try to split along" << findID(poly.at(i)) << findID(poly.at(j)); QLineF line(poly.at(i),poly.at(j)); QPointF middle = (poly.at(i)+poly.at(j))/2.0; if(!poly.containsPoint(middle,Qt::WindingFill)) continue; if(!intersects(poly,line)){ QPolygonF p1,p2; //QStringList poly1id,poly2id; for(int k=i;k<=j;k++){ p1 << poly.at(k); //poly1id << findID(poly.at(k)); } p1 << poly.at(i); //poly1id << findID(poly.at(i)); for(int k=j;k<poly.size()-1;k++){ p2 << poly.at(k); //poly2id << findID(poly.at(k)); } for(int k=0;k<=i;k++){ p2 << poly.at(k); //poly2id << findID(poly.at(k)); } p2 << poly.at(j); //poly2id << findID(poly.at(j)); //qDebug() << poly.size() << QPair<int,QString>(i,findID(poly.at(i))) << QPair<int,QString>(j,findID(poly.at(j))) << p1.size() << p2.size(); //qDebug() << "Poly1" << poly1id; //qDebug() << "Poly2" << poly2id; mesh_.push_back(p1); mesh_.push_back(p2); mesh_.removeAt(id); splitDiag(); return; } } } //qDebug() << "Can't split poly " << polyID; } }
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); int i, maxCount; bool isRing = false; double offsetAlongLine = mOffsetAlongLine; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE ) ) { context.setOriginalValueVariable( mOffsetAlongLine ); offsetAlongLine = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE, context, mOffsetAlongLine ).toDouble(); } if ( offsetAlongLine != 0 ) { //scale offset along line offsetAlongLine = QgsSymbolLayerV2Utils::convertToPainterUnits( rc, offsetAlongLine, mOffsetAlongLineUnit, mOffsetAlongLineMapUnitScale ); } if ( offsetAlongLine == 0 && context.renderContext().geometry() && context.renderContext().geometry()->hasCurvedSegments() && ( placement == Vertex || placement == CurvePoint ) ) { const QgsCoordinateTransform* ct = context.renderContext().coordinateTransform(); const QgsMapToPixel& mtp = context.renderContext().mapToPixel(); QgsVertexId vId; QgsPointV2 vPoint; double x, y, z; QPointF mapPoint; while ( context.renderContext().geometry()->nextVertex( vId, vPoint ) ) { if (( placement == Vertex && vId.type == QgsVertexId::SegmentVertex ) || ( placement == CurvePoint && vId.type == QgsVertexId::CurveVertex ) ) { //transform x = vPoint.x(), y = vPoint.y(); z = vPoint.z(); if ( ct ) { ct->transformInPlace( x, y, z ); } mapPoint.setX( x ); mapPoint.setY( y ); mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() ); if ( mRotateMarker ) { double angle = context.renderContext().geometry()->vertexAngle( vId ); mMarker->setAngle( angle * 180 / M_PI ); } mMarker->renderPoint( mapPoint, context.feature(), rc, -1, context.selected() ); } } return; } if ( placement == FirstVertex ) { i = 0; maxCount = 1; } else if ( placement == LastVertex ) { i = points.count() - 1; maxCount = points.count(); } else if ( placement == Vertex ) { i = 0; maxCount = points.count(); if ( points.first() == points.last() ) isRing = true; } else { return; } if ( offsetAlongLine > 0 && ( placement == FirstVertex || placement == LastVertex ) ) { double distance; distance = placement == FirstVertex ? offsetAlongLine : -offsetAlongLine; renderOffsetVertexAlongLine( points, i, distance, context ); // restore original rotation mMarker->setAngle( origAngle ); return; } for ( ; i < maxCount; ++i ) { if ( isRing && placement == Vertex && i == points.count() - 1 ) { continue; // don't draw the last marker - it has been drawn already } // rotate marker (if desired) if ( mRotateMarker ) { double angle = markerAngle( points, isRing, i ); mMarker->setAngle( origAngle + angle * 180 / M_PI ); } mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() ); } // restore original rotation mMarker->setAngle( origAngle ); }
void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { if ( points.isEmpty() ) return; QPointF lastPt = points[0]; double lengthLeft = 0; // how much is left until next marker bool first = mOffsetAlongLine ? false : true; //only draw marker at first vertex when no offset along line is set QgsRenderContext& rc = context.renderContext(); double interval = mInterval; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_INTERVAL ) ) { context.setOriginalValueVariable( mInterval ); interval = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_INTERVAL, context, mInterval ).toDouble(); } if ( interval <= 0 ) { interval = 0.1; } double offsetAlongLine = mOffsetAlongLine; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE ) ) { context.setOriginalValueVariable( mOffsetAlongLine ); offsetAlongLine = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE, context, mOffsetAlongLine ).toDouble(); } double painterUnitInterval = QgsSymbolLayerV2Utils::convertToPainterUnits( rc, interval, mIntervalUnit, mIntervalMapUnitScale ); lengthLeft = painterUnitInterval - QgsSymbolLayerV2Utils::convertToPainterUnits( rc, offsetAlongLine, mIntervalUnit, mIntervalMapUnitScale ); for ( int i = 1; i < points.count(); ++i ) { const QPointF& pt = points[i]; if ( lastPt == pt ) // must not be equal! continue; // for each line, find out dx and dy, and length MyLine l( lastPt, pt ); QPointF diff = l.diffForInterval( painterUnitInterval ); // if there's some length left from previous line // use only the rest for the first point in new line segment double c = 1 - lengthLeft / painterUnitInterval; lengthLeft += l.length(); // rotate marker (if desired) if ( mRotateMarker ) { mMarker->setLineAngle( l.angle() * 180 / M_PI ); } // draw first marker if ( first ) { mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() ); first = false; } // while we're not at the end of line segment, draw! while ( lengthLeft > painterUnitInterval ) { // "c" is 1 for regular point or in interval (0,1] for begin of line segment lastPt += c * diff; lengthLeft -= painterUnitInterval; mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() ); c = 1; // reset c (if wasn't 1 already) } lastPt = pt; } }
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement ) { if ( points.isEmpty() ) return; QgsRenderContext& rc = context.renderContext(); double origAngle = mMarker->angle(); int i, maxCount; bool isRing = false; double offsetAlongLine = mOffsetAlongLine; QgsExpression* offsetAlongLineExpression = expression( "offset_along_line" ); if ( offsetAlongLineExpression ) { offsetAlongLine = offsetAlongLineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } if ( offsetAlongLine != 0 ) { //scale offset along line offsetAlongLine *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mOffsetAlongLineUnit, mOffsetAlongLineMapUnitScale ); } if ( placement == FirstVertex ) { i = 0; maxCount = 1; } else if ( placement == LastVertex ) { i = points.count() - 1; maxCount = points.count(); } else { i = 0; maxCount = points.count(); if ( points.first() == points.last() ) isRing = true; } if ( offsetAlongLine > 0 && ( placement == FirstVertex || placement == LastVertex ) ) { double distance; distance = placement == FirstVertex ? offsetAlongLine : -offsetAlongLine; renderOffsetVertexAlongLine( points, i, distance, context ); // restore original rotation mMarker->setAngle( origAngle ); return; } for ( ; i < maxCount; ++i ) { if ( isRing && placement == Vertex && i == points.count() - 1 ) { continue; // don't draw the last marker - it has been drawn already } // rotate marker (if desired) if ( mRotateMarker ) { double angle = markerAngle( points, isRing, i ); mMarker->setAngle( origAngle + angle * 180 / M_PI ); } mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() ); } // restore original rotation mMarker->setAngle( origAngle ); }
void _PolyClipper::clipPolyline(const QPolygonF& poly) { // exit if fewer than 2 points in polygon if ( poly.size() < 2 ) return; // output goes here QPolygonF pout; QPolygonF::const_iterator polyiter = poly.begin(); QPointF lastpt = *polyiter; polyiter++; for( ; polyiter != poly.end(); ++polyiter ) { QPointF p1 = lastpt; QPointF p2 = *polyiter; bool plotline = _clipper.clipLine(p1, p2); if( plotline ) { if( pout.isEmpty() ) { // add first line pout << p1; if( ! smallDelta(p1, p2) ) pout << p2; } else { if( p1 == pout.last() ) { if( ! smallDelta(p1, p2) ) // extend polyline pout << p2; } else { // paint existing line if( pout.size() >= 2 ) emitPolyline(pout); // start new line pout.clear(); pout << p1; if( ! smallDelta(p1, p2) ) pout << p2; } } } else { // line isn't in region, so ignore results from clip function // paint existing line if( pout.size() >= 2 ) emitPolyline(pout); // cleanup pout.clear(); } lastpt = *polyiter; } if( pout.size() >= 2 ) emitPolyline(pout); }
QgsConstWkbPtr QgsClipper::clippedLineWKB( QgsConstWkbPtr& wkbPtr, const QgsRectangle& clipExtent, QPolygonF& line ) { QgsWKBTypes::Type wkbType = wkbPtr.readHeader(); int nPoints; wkbPtr >> nPoints; int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double ); if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() ) { QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) ); return QgsConstWkbPtr( nullptr, 0 ); } double p0x, p0y, p1x = 0.0, p1y = 0.0; //original coordinates double p1x_c, p1y_c; //clipped end coordinates double lastClipX = 0.0, lastClipY = 0.0; //last successfully clipped coords QPolygonF pts; wkbPtr -= sizeof( unsigned int ); wkbPtr >> pts; nPoints = pts.size(); line.clear(); line.reserve( nPoints + 1 ); QPointF *ptr = pts.data(); for ( int i = 0; i < nPoints; ++i, ++ptr ) { if ( i == 0 ) { p1x = ptr->rx(); p1y = ptr->ry(); continue; } else { p0x = p1x; p0y = p1y; p1x = ptr->rx(); p1y = ptr->ry(); p1x_c = p1x; p1y_c = p1y; if ( clipLineSegment( clipExtent.xMinimum(), clipExtent.xMaximum(), clipExtent.yMinimum(), clipExtent.yMaximum(), p0x, p0y, p1x_c, p1y_c ) ) { bool newLine = !line.isEmpty() && ( !qgsDoubleNear( p0x, lastClipX ) || !qgsDoubleNear( p0y, lastClipY ) ); if ( newLine ) { //add edge points to connect old and new line connectSeparatedLines( lastClipX, lastClipY, p0x, p0y, clipExtent, line ); } if ( line.size() < 1 || newLine ) { //add first point line << QPointF( p0x, p0y ); } //add second point lastClipX = p1x_c; lastClipY = p1y_c; line << QPointF( p1x_c, p1y_c ); } } } return wkbPtr; }
void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { if ( points.isEmpty() ) return; QPointF lastPt = points[0]; double lengthLeft = 0; // how much is left until next marker bool first = true; double origAngle = mMarker->angle(); double painterUnitInterval = context.outputLineWidth( mInterval > 0 ? mInterval : 0.1 ); QgsRenderContext& rc = context.renderContext(); for ( int i = 1; i < points.count(); ++i ) { const QPointF& pt = points[i]; if ( lastPt == pt ) // must not be equal! continue; // for each line, find out dx and dy, and length MyLine l( lastPt, pt ); QPointF diff = l.diffForInterval( painterUnitInterval ); // if there's some length left from previous line // use only the rest for the first point in new line segment double c = 1 - lengthLeft / painterUnitInterval; lengthLeft += l.length(); // rotate marker (if desired) if ( mRotateMarker ) { mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) ); } // draw first marker if ( first ) { mMarker->renderPoint( lastPt, rc, -1, context.selected() ); first = false; } // while we're not at the end of line segment, draw! while ( lengthLeft > painterUnitInterval ) { // "c" is 1 for regular point or in interval (0,1] for begin of line segment lastPt += c * diff; lengthLeft -= painterUnitInterval; mMarker->renderPoint( lastPt, rc, -1, context.selected() ); c = 1; // reset c (if wasn't 1 already) } lastPt = pt; } // restore original rotation mMarker->setAngle( origAngle ); }
void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { if ( points.isEmpty() ) return; QPointF lastPt = points[0]; double lengthLeft = 0; // how much is left until next marker bool first = mOffsetAlongLine ? false : true; //only draw marker at first vertex when no offset along line is set double origAngle = mMarker->angle(); QgsRenderContext& rc = context.renderContext(); double interval = mInterval; QgsExpression* intervalExpression = expression( "interval" ); if ( intervalExpression ) { interval = intervalExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } if ( interval <= 0 ) { interval = 0.1; } double offsetAlongLine = mOffsetAlongLine; QgsExpression* offsetAlongLineExpression = expression( "offset_along_line" ); if ( offsetAlongLineExpression ) { offsetAlongLine = offsetAlongLineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble(); } double painterUnitInterval = interval * QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mIntervalUnit, mIntervalMapUnitScale ); lengthLeft = painterUnitInterval - offsetAlongLine * QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mIntervalUnit, mIntervalMapUnitScale ); for ( int i = 1; i < points.count(); ++i ) { const QPointF& pt = points[i]; if ( lastPt == pt ) // must not be equal! continue; // for each line, find out dx and dy, and length MyLine l( lastPt, pt ); QPointF diff = l.diffForInterval( painterUnitInterval ); // if there's some length left from previous line // use only the rest for the first point in new line segment double c = 1 - lengthLeft / painterUnitInterval; lengthLeft += l.length(); // rotate marker (if desired) if ( mRotateMarker ) { mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) ); } // draw first marker if ( first ) { mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() ); first = false; } // while we're not at the end of line segment, draw! while ( lengthLeft > painterUnitInterval ) { // "c" is 1 for regular point or in interval (0,1] for begin of line segment lastPt += c * diff; lengthLeft -= painterUnitInterval; mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() ); c = 1; // reset c (if wasn't 1 already) } lastPt = pt; } // restore original rotation mMarker->setAngle( origAngle ); }
void GpxLayer::load(const QString &filename) { QFile file(filename); if (file.open(QIODevice::ReadOnly)) { QXmlStreamReader xml(&file); QPolygonF points; QList<float> elev; QList<int> time; QString tag, tag2; QString name; QPointF pos; while (!xml.atEnd()) { xml.readNext(); if (xml.isStartElement()) { if (xml.name() == "trkpt") { tag = "trkpt"; float lat = xml.attributes().value("lat").toString().toFloat(); float lon = xml.attributes().value("lon").toString().toFloat(); points << QPointF(Projection::lon2rawx(lon), Projection::lat2rawy(lat)); } else if (xml.name() == "ele") { tag2 = "ele"; } else if (xml.name() == "time") { tag2 = "time"; } else if (xml.name() == "wpt") { tag = "wpt"; float lat = xml.attributes().value("lat").toString().toFloat(); float lon = xml.attributes().value("lon").toString().toFloat(); pos = QPointF(lon, lat); } else if (xml.name() == "name") { tag2 = "name"; } else if (xml.name() == "trk" || xml.name() == "trkseg") { } else { tag2.clear(); } } else if (xml.isEndElement()) { if (xml.name() == "trkseg") { if (!points.isEmpty()) { m_track << points; m_track << QPointF(); } points.clear(); elev.clear(); time.clear(); } else if (xml.name() == "wpt") { //addMarker(pos, name); name.clear(); } } else if (xml.isCharacters() && !xml.isWhitespace()) { if (tag == "trkpt") { if (tag2 == "ele") { elev << xml.text().toString().toFloat(); } else if (tag2 == "time") { QDateTime dt = QDateTime::fromString(xml.text().toString(), Qt::ISODate); time << dt.toTime_t(); } } else if (tag == "wpt") { if (tag2 == "name") { name = xml.text().toString(); } } } } zoom(0); } }
void BarDiagram::BarDiagramType::paintBars( PaintContext* ctx, const QModelIndex& index, const QRectF& bar, qreal maxDepth ) { PainterSaver painterSaver( ctx->painter() ); //Pending Michel: configure threeDBrush settings - shadowColor etc... QBrush indexBrush( diagram()->brush( index ) ); QPen indexPen( diagram()->pen( index ) ); ctx->painter()->setRenderHint( QPainter::Antialiasing, diagram()->antiAliasing() ); ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( index ); if ( threeDAttrs.isEnabled() ) { indexBrush = threeDAttrs.threeDBrush( indexBrush, bar ); } ctx->painter()->setBrush( indexBrush ); ctx->painter()->setPen( PrintingParameters::scalePen( indexPen ) ); if ( threeDAttrs.isEnabled() ) { if ( maxDepth ) { threeDAttrs.setDepth( -maxDepth ); } //fixme adjust the painting to reasonable depth value const qreal usedDepth = threeDAttrs.depth() * ( type() == BarDiagram::Normal ? 0.25 : 1.0 ); const QRectF isoRect = bar.translated( usedDepth, -usedDepth ); // we need to find out if the height is negative // and in this case paint it up and down QPolygonF topPoints; if ( isoRect.height() < 0 ) { if ( !( type() == BarDiagram::Stacked && index.column() != 0 ) ) { // fix it when several negative stacked values topPoints << isoRect.bottomLeft() << isoRect.bottomRight() << bar.bottomRight() << bar.bottomLeft(); } } else { reverseMapper().addRect( index.row(), index.column(), isoRect ); ctx->painter()->drawRect( isoRect ); if ( !( type() == BarDiagram::Percent && isoRect.height() == 0 ) ) { topPoints << bar.topLeft() << bar.topRight() << isoRect.topRight() << isoRect.topLeft(); } } bool noClippingForTop = false; if ( !topPoints.isEmpty() ) { // Draw the top, if at least one of the top's points is // either inside or near at the edge of the coordinate plane: bool drawIt = false; bool hasPointOutside = false; const QRectF r( ctx->rectangle().adjusted( 0, -1, 1, 0 ) ); Q_FOREACH( QPointF pt, topPoints ) { if ( r.contains( pt ) ) { drawIt = true; } else { hasPointOutside = true; } } if ( drawIt ) { const PainterSaver p( ctx->painter() ); noClippingForTop = hasPointOutside && ctx->painter()->hasClipping(); if ( noClippingForTop ) { ctx->painter()->setClipping( false ); } reverseMapper().addPolygon( index.row(), index.column(), topPoints ); ctx->painter()->drawPolygon( topPoints ); } } if ( bar.height() != 0 ) { const PainterSaver p( ctx->painter() ); if ( noClippingForTop ) { ctx->painter()->setClipping( false ); } QPolygonF sidePoints; sidePoints << bar.topRight() << isoRect.topRight() << isoRect.bottomRight() << bar.bottomRight(); reverseMapper().addPolygon( index.row(), index.column(), sidePoints ); ctx->painter()->drawPolygon( sidePoints ); } }
void assertPolygonIsClosed(QPolygonF polygon) { ASSERT_RETURN(polygon.isEmpty() || polygon.first() == polygon.last()); }