void QgsMeshLayerRenderer::renderMesh( const std::unique_ptr<QgsSymbol> &symbol, const QVector<QgsMeshFace> &faces ) { if ( !symbol ) return; QgsFields fields; QgsSingleSymbolRenderer renderer( symbol->clone() ); renderer.startRender( mContext, fields ); for ( int i = 0; i < faces.size(); ++i ) { if ( mContext.renderingStopped() ) break; const QgsMeshFace &face = faces[i]; QgsFeature feat; feat.setFields( fields ); QVector<QgsPointXY> ring; for ( int j = 0; j < face.size(); ++j ) { int vertex_id = face[j]; Q_ASSERT( vertex_id < mTriangularMesh.vertices().size() ); //Triangular mesh vertices contains also native mesh vertices const QgsPoint &vertex = mTriangularMesh.vertices()[vertex_id]; ring.append( vertex ); } QgsPolygonXY polygon; polygon.append( ring ); QgsGeometry geom = QgsGeometry::fromPolygonXY( polygon ); feat.setGeometry( geom ); renderer.renderFeature( feat, mContext ); } renderer.stopRender( mContext ); }
void QgsMapToolOffsetCurve::applyOffset( double offset, Qt::KeyboardModifiers modifiers ) { if ( !mLayer || offset == 0.0 ) { cancel(); notifyNotVectorLayer(); return; } updateGeometryAndRubberBand( offset ); // no modification if ( !mGeometryModified ) { mLayer->destroyEditCommand(); cancel(); return; } if ( mModifiedPart >= 0 ) { QgsGeometry geometry; int partIndex = 0; QgsWkbTypes::Type geomType = mOriginalGeometry.wkbType(); if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::LineGeometry ) { QgsMultiPolylineXY newMultiLine; QgsMultiPolylineXY multiLine = mOriginalGeometry.asMultiPolyline(); QgsMultiPolylineXY::const_iterator it = multiLine.constBegin(); for ( ; it != multiLine.constEnd(); ++it ) { if ( partIndex == mModifiedPart ) { newMultiLine.append( mModifiedGeometry.asPolyline() ); } else { newMultiLine.append( *it ); } partIndex++; } geometry = QgsGeometry::fromMultiPolylineXY( newMultiLine ); } else { QgsMultiPolygonXY newMultiPoly; const QgsMultiPolygonXY multiPoly = mOriginalGeometry.asMultiPolygon(); QgsMultiPolygonXY::const_iterator multiPolyIt = multiPoly.constBegin(); for ( ; multiPolyIt != multiPoly.constEnd(); ++multiPolyIt ) { if ( partIndex == mModifiedPart ) { if ( mModifiedGeometry.isMultipart() ) { // not a ring if ( mModifiedRing <= 0 ) { // part became mulitpolygon, that means discard original rings from the part newMultiPoly += mModifiedGeometry.asMultiPolygon(); } else { // ring became multipolygon, oh boy! QgsPolygonXY newPoly; int ringIndex = 0; QgsPolygonXY::const_iterator polyIt = multiPolyIt->constBegin(); for ( ; polyIt != multiPolyIt->constEnd(); ++polyIt ) { if ( ringIndex == mModifiedRing ) { const QgsMultiPolygonXY ringParts = mModifiedGeometry.asMultiPolygon(); QgsPolygonXY newRings; QgsMultiPolygonXY::const_iterator ringIt = ringParts.constBegin(); for ( ; ringIt != ringParts.constEnd(); ++ringIt ) { // the different parts of the new rings cannot have rings themselves newRings.append( ringIt->at( 0 ) ); } newPoly += newRings; } else { newPoly.append( *polyIt ); } ringIndex++; } newMultiPoly.append( newPoly ); } } else { // original part had no ring if ( mModifiedRing == -1 ) { newMultiPoly.append( mModifiedGeometry.asPolygon() ); } else { QgsPolygonXY newPoly; int ringIndex = 0; QgsPolygonXY::const_iterator polyIt = multiPolyIt->constBegin(); for ( ; polyIt != multiPolyIt->constEnd(); ++polyIt ) { if ( ringIndex == mModifiedRing ) { newPoly.append( mModifiedGeometry.asPolygon().at( 0 ) ); } else { newPoly.append( *polyIt ); } ringIndex++; } newMultiPoly.append( newPoly ); } } } else { newMultiPoly.append( *multiPolyIt ); } partIndex++; } geometry = QgsGeometry::fromMultiPolygonXY( newMultiPoly ); } geometry.convertToMultiType(); mModifiedGeometry = geometry; } else if ( mModifiedRing >= 0 ) { // original geometry had some rings if ( mModifiedGeometry.isMultipart() ) { // not a ring if ( mModifiedRing == 0 ) { // polygon became mulitpolygon, that means discard original rings from the part // keep the modified geometry as is } else { QgsPolygonXY newPoly; const QgsPolygonXY poly = mOriginalGeometry.asPolygon(); // ring became multipolygon, oh boy! int ringIndex = 0; QgsPolygonXY::const_iterator polyIt = poly.constBegin(); for ( ; polyIt != poly.constEnd(); ++polyIt ) { if ( ringIndex == mModifiedRing ) { QgsMultiPolygonXY ringParts = mModifiedGeometry.asMultiPolygon(); QgsPolygonXY newRings; QgsMultiPolygonXY::const_iterator ringIt = ringParts.constBegin(); for ( ; ringIt != ringParts.constEnd(); ++ringIt ) { // the different parts of the new rings cannot have rings themselves newRings.append( ringIt->at( 0 ) ); } newPoly += newRings; } else { newPoly.append( *polyIt ); } ringIndex++; } mModifiedGeometry = QgsGeometry::fromPolygonXY( newPoly ); } } else { // simple case where modified geom is a polygon (not multi) QgsPolygonXY newPoly; const QgsPolygonXY poly = mOriginalGeometry.asPolygon(); int ringIndex = 0; QgsPolygonXY::const_iterator polyIt = poly.constBegin(); for ( ; polyIt != poly.constEnd(); ++polyIt ) { if ( ringIndex == mModifiedRing ) { newPoly.append( mModifiedGeometry.asPolygon().at( 0 ) ); } else { newPoly.append( *polyIt ); } ringIndex++; } mModifiedGeometry = QgsGeometry::fromPolygonXY( newPoly ); } } if ( !mModifiedGeometry.isGeosValid() ) { emit messageEmitted( tr( "Generated geometry is not valid." ), Qgis::Critical ); // no cancel, continue editing. return; } mLayer->beginEditCommand( tr( "Offset curve" ) ); bool editOk; if ( !mCtrlHeldOnFirstClick && !( modifiers & Qt::ControlModifier ) ) { editOk = mLayer->changeGeometry( mModifiedFeature, mModifiedGeometry ); } else { QgsFeature f; f.setGeometry( mModifiedGeometry ); //add empty values for all fields (allows inserting attribute values via the feature form in the same session) QgsAttributes attrs( mLayer->fields().count() ); const QgsFields &fields = mLayer->fields(); for ( int idx = 0; idx < fields.count(); ++idx ) { attrs[idx] = QVariant(); } f.setAttributes( attrs ); editOk = mLayer->addFeature( f ); } if ( editOk ) { mLayer->endEditCommand(); } else { mLayer->destroyEditCommand(); emit messageEmitted( QStringLiteral( "Could not apply offset" ), Qgis::Critical ); } deleteRubberBandAndGeometry(); deleteUserInputWidget(); mLayer->triggerRepaint(); mLayer = nullptr; }