double QgsComposerScaleBar::mapWidth() const { if ( !mComposerMap ) { return 0.0; } QgsRectangle composerMapRect = mComposerMap->extent(); if ( mUnits == MapUnits ) { return composerMapRect.width(); } else { QgsDistanceArea da; da.setEllipsoidalMode( mComposerMap->mapRenderer()->hasCrsTransformEnabled() ); da.setSourceCrs( mComposerMap->mapRenderer()->destinationCrs().srsid() ); da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", "WGS84" ) ); double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) ); if ( mUnits == Feet ) { measure /= 0.3048; } return measure; } }
double QgsComposerScaleBar::mapDiagonal() const { if ( !mComposerMap ) { return 0.0; } QgsRectangle composerMapRect = mComposerMap->extent(); if ( mUnits == MapUnits ) { return sqrt( composerMapRect.width() * composerMapRect.width() + composerMapRect.height() * composerMapRect.height() ); } else { QgsDistanceArea da; da.setProjectionsEnabled( true ); da.setSourceCrs( mComposerMap->mapRenderer()->destinationCrs().srsid() ); QSettings s; da.setEllipsoid( s.value( "/qgis/measure/ellipsoid", "WGS84" ).toString() ); double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMaximum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) ); if ( mUnits == Feet ) { measure /= 0.3048; } return measure; } }
double QgsLayoutItemScaleBar::mapWidth() const { if ( !mMap ) { return 0.0; } QgsRectangle mapExtent = mMap->extent(); if ( mSettings.units() == QgsUnitTypes::DistanceUnknownUnit ) { return mapExtent.width(); } else { QgsDistanceArea da; da.setSourceCrs( mMap->crs(), mLayout->project()->transformContext() ); da.setEllipsoid( mLayout->project()->ellipsoid() ); QgsUnitTypes::DistanceUnit units = da.lengthUnits(); double measure = da.measureLine( QgsPointXY( mapExtent.xMinimum(), mapExtent.yMinimum() ), QgsPointXY( mapExtent.xMaximum(), mapExtent.yMinimum() ) ); measure /= QgsUnitTypes::fromUnitToUnitFactor( mSettings.units(), units ); return measure; } }
void QgsAttributeActionDialog::insertExpression() { QString selText = actionAction->textCursor().selectedText(); // edit the selected expression if there's one if ( selText.startsWith( "[%" ) && selText.endsWith( "%]" ) ) selText = selText.mid( 2, selText.size() - 4 ); // display the expression builder QgsExpressionContext context; context << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope() << QgsExpressionContextUtils::layerScope( mActions->layer() ); QgsExpressionBuilderDialog dlg( mActions->layer(), selText, this, "generic", context ); dlg.setWindowTitle( tr( "Insert expression" ) ); QgsDistanceArea myDa; myDa.setSourceCrs( mActions->layer()->crs().srsid() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); dlg.setGeomCalculator( myDa ); if ( dlg.exec() == QDialog::Accepted ) { QString expression = dlg.expressionBuilder()->expressionText(); //Only add the expression if the user has entered some text. if ( !expression.isEmpty() ) { actionAction->insertPlainText( "[%" + expression + "%]" ); } } }
double QgsComposerScaleBar::mapWidth() const { if ( !mComposerMap ) { return 0.0; } QgsRectangle composerMapRect = *( mComposerMap->currentMapExtent() ); if ( mUnits == MapUnits ) { return composerMapRect.width(); } else { QgsDistanceArea da; da.setEllipsoidalMode( mComposition->mapSettings().hasCrsTransformEnabled() ); da.setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() ); da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", "WGS84" ) ); double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) ); if ( mUnits == QgsComposerScaleBar::Feet ) { measure /= QGis::fromUnitToUnitFactor( QGis::Feet, QGis::Meters ); } else if ( mUnits == QgsComposerScaleBar::NauticalMiles ) { measure /= QGis::fromUnitToUnitFactor( QGis::NauticalMiles, QGis::Meters ); } return measure; } }
QgsAttributeActionPropertiesDialog::QgsAttributeActionPropertiesDialog( QgsVectorLayer* layer, QWidget* parent ) : QDialog( parent ) , mLayer( layer ) { setupUi( this ); // display the expression builder QgsExpressionContext context; context << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope() << QgsExpressionContextUtils::layerScope( mLayer ); QgsDistanceArea myDa; myDa.setSourceCrs( mLayer->crs().srsid() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->ellipsoid() ); mFieldExpression->setLayer( mLayer ); mFieldExpression->setGeomCalculator( myDa ); connect( mBrowseButton, SIGNAL( clicked( bool ) ), this, SLOT( browse() ) ); connect( mInsertFieldOrExpression, SIGNAL( clicked( bool ) ), this, SLOT( insertExpressionOrField() ) ); connect( mActionName, SIGNAL( textChanged( QString ) ), this, SLOT( updateButtons() ) ); connect( mActionText, SIGNAL( textChanged() ), this, SLOT( updateButtons() ) ); updateButtons(); }
void GlobePlugin::syncExtent() { QgsMapCanvas* mapCanvas = mQGisIface->mapCanvas(); QgsMapRenderer* mapRenderer = mapCanvas->mapRenderer(); QgsRectangle extent = mapCanvas->extent(); osgEarth::Util::EarthManipulator* manip = dynamic_cast<osgEarth::Util::EarthManipulator*>( mOsgViewer->getCameraManipulator() ); //rotate earth to north and perpendicular to camera manip->setRotation( osg::Quat() ); QgsDistanceArea dist; dist.setSourceCrs( mapRenderer->destinationCrs().srsid() ); dist.setEllipsoidalMode( mapRenderer->hasCrsTransformEnabled() ); dist.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); QgsPoint ll = QgsPoint( extent.xMinimum(), extent.yMinimum() ); QgsPoint ul = QgsPoint( extent.xMinimum(), extent.yMaximum() ); double height = dist.measureLine( ll, ul ); //camera viewing angle double viewAngle = 30; //camera distance double distance = height / tan( viewAngle * osg::PI / 180 ); //c = b*cotan(B(rad)) OE_NOTICE << "map extent: " << height << " camera distance: " << distance << std::endl; osgEarth::Util::Viewpoint viewpoint( osg::Vec3d( extent.center().x(), extent.center().y(), 0.0 ), 0.0, -90.0, distance ); manip->setViewpoint( viewpoint, 4.0 ); }
void QgsMeasureDialog::configureDistanceArea( QgsDistanceArea& da ) { QSettings settings; QString ellipsoidId = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString(); da.setSourceCrs( mTool->canvas()->mapRenderer()->destinationCrs().srsid() ); da.setEllipsoid( ellipsoidId ); da.setProjectionsEnabled( mcbProjectionEnabled->isChecked() ); }
void QgsMapToolMeasureAngle::configureDistanceArea( QgsDistanceArea& da ) { QSettings settings; QString ellipsoidId = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString(); da.setSourceCrs( mCanvas->mapRenderer()->destinationCrs().srsid() ); da.setEllipsoid( ellipsoidId ); da.setProjectionsEnabled( mResultDisplay->projectionEnabled() ); }
void TestQgsDistanceArea::emptyPolygon() { QgsDistanceArea da; da.setSourceCrs( 3452 ); da.setEllipsoidalMode( true ); da.setEllipsoid( "WGS84" ); //test that measuring an empty polygon doesn't crash da.measurePolygon( QList< QgsPoint >() ); }
void TestQgsDistanceArea::regression13601() { //test regression #13601 QgsDistanceArea calc; calc.setEllipsoidalMode( true ); calc.setEllipsoid( "NONE" ); calc.setSourceCrs( 1108L ); QgsGeometry geom( QgsGeometryFactory::geomFromWkt( "Polygon ((252000 1389000, 265000 1389000, 265000 1385000, 252000 1385000, 252000 1389000))" ) ); QVERIFY( qgsDoubleNear( calc.measureArea( &geom ), 52000000, 0.0001 ) ); }
QDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &f ) { QgsDistanceArea myDa; myDa.setSourceCrs( l->crs().srsid() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &f, false, myDa ); return dialog->dialog(); }
void TestQgsDistanceArea::regression14675() { //test regression #14675 QgsDistanceArea calc; calc.setEllipsoidalMode( true ); calc.setEllipsoid( "GRS80" ); calc.setSourceCrs( 145L ); QgsGeometry geom( QgsGeometryFactory::geomFromWkt( "Polygon ((917593.5791854317067191 6833700.00807378999888897, 917596.43389983859378844 6833700.67099479306489229, 917599.53056440979707986 6833700.78673478215932846, 917593.5791854317067191 6833700.00807378999888897))" ) ); //lots of tolerance here - the formulas get quite unstable with small areas due to division by very small floats QGSCOMPARENEAR( calc.measureArea( &geom ), 0.83301, 0.02 ); }
double Heatmap::mapUnitsOf( double meters, QgsCoordinateReferenceSystem layerCrs ) { // Worker to transform metres input to mapunits QgsDistanceArea da; da.setSourceCrs( layerCrs.srsid() ); da.setEllipsoid( layerCrs.ellipsoidAcronym() ); if ( da.geographic() ) { da.setEllipsoidalMode( true ); } return meters / da.measureLine( QgsPoint( 0.0, 0.0 ), QgsPoint( 0.0, 1.0 ) ); }
double HeatmapGui::mapUnitsOf( double dist, const QgsCoordinateReferenceSystem& layerCrs ) const { // converter function to transform layer input to mapunits // so that bounding box can be updated QgsDistanceArea da; da.setSourceCrs( layerCrs.srsid() ); da.setEllipsoid( layerCrs.ellipsoidAcronym() ); if ( da.geographic() ) { da.setEllipsoidalMode( true ); } double unitDistance = da.measureLine( QgsPoint( 0.0, 0.0 ), QgsPoint( 0.0, 1.0 ) ); QgsDebugMsg( QString( "Converted %1 layer to %2 map units" ).arg( dist ).arg( dist / unitDistance ) ); return dist / unitDistance; }
QgsAttributeDialog *QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &feature ) { QgsDistanceArea myDa; myDa.setSourceCrs( l->crs() ); myDa.setEllipsoid( QgsProject::instance()->ellipsoid() ); QgsAttributeEditorContext context; context.setDistanceArea( myDa ); context.setVectorLayerTools( qgis->vectorLayerTools() ); QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, qgis, true, context ); if ( !feature.isValid() ) { dialog->setMode( QgsAttributeForm::AddFeatureMode ); } return dialog; }
QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature ) { QgsFeature *f = cloneFeature ? new QgsFeature( *mFeature ) : mFeature; QgsAttributeEditorContext context; QgsDistanceArea myDa; myDa.setSourceCrs( mLayer->crs() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); context.setDistanceArea( myDa ); context.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() ); QgsAttributeDialog *dialog = new QgsAttributeDialog( mLayer, f, cloneFeature, NULL, true, context ); if ( mLayer->actions()->size() > 0 ) { dialog->setContextMenuPolicy( Qt::ActionsContextMenu ); QAction *a = new QAction( tr( "Run actions" ), dialog ); a->setEnabled( false ); dialog->addAction( a ); for ( int i = 0; i < mLayer->actions()->size(); i++ ) { const QgsAction &action = mLayer->actions()->at( i ); if ( !action.runable() ) continue; QgsFeature& feat = const_cast<QgsFeature&>( *dialog->feature() ); QgsFeatureAction *a = new QgsFeatureAction( action.name(), feat, mLayer, i, -1, dialog ); dialog->addAction( a ); connect( a, SIGNAL( triggered() ), a, SLOT( execute() ) ); QAbstractButton *pb = dialog->findChild<QAbstractButton *>( action.name() ); if ( pb ) connect( pb, SIGNAL( clicked() ), a, SLOT( execute() ) ); } } return dialog; }
QgsAttributeDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &feature ) { QgsDistanceArea myDa; myDa.setSourceCrs( l->crs().srsid() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); QgsAttributeEditorContext context; context.setDistanceArea( myDa ); context.setVectorLayerTools( qgis->vectorLayerTools() ); QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, qgis, true, context ); if ( !feature.isValid() ) { dialog->setMode( QgsAttributeForm::AddFeatureMode ); } return dialog; }
QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature ) { QgsFeature *f = cloneFeature ? new QgsFeature( *mFeature ) : mFeature; QgsAttributeEditorContext context; QgsDistanceArea myDa; myDa.setSourceCrs( mLayer->crs() ); myDa.setEllipsoid( QgsProject::instance()->ellipsoid() ); context.setDistanceArea( myDa ); context.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() ); context.setFormMode( QgsAttributeEditorContext::StandaloneDialog ); QgsAttributeDialog *dialog = new QgsAttributeDialog( mLayer, f, cloneFeature, parentWidget(), true, context ); dialog->setWindowFlags( dialog->windowFlags() | Qt::Tool ); dialog->setObjectName( QStringLiteral( "featureactiondlg:%1:%2" ).arg( mLayer->id() ).arg( f->id() ) ); QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral( "Feature" ) ); if ( !actions.isEmpty() ) { dialog->setContextMenuPolicy( Qt::ActionsContextMenu ); QAction *a = new QAction( tr( "Run actions" ), dialog ); a->setEnabled( false ); dialog->addAction( a ); Q_FOREACH ( const QgsAction &action, actions ) { if ( !action.runable() ) continue; QgsFeature &feat = const_cast<QgsFeature &>( *dialog->feature() ); QgsFeatureAction *a = new QgsFeatureAction( action.name(), feat, mLayer, action.id(), -1, dialog ); dialog->addAction( a ); connect( a, &QAction::triggered, a, &QgsFeatureAction::execute ); QAbstractButton *pb = dialog->findChild<QAbstractButton *>( action.name() ); if ( pb ) connect( pb, &QAbstractButton::clicked, a, &QgsFeatureAction::execute ); } }
void GlobePlugin::syncExtent() { QgsMapCanvas* mapCanvas = mQGisIface->mapCanvas(); const QgsMapSettings &mapSettings = mapCanvas->mapSettings(); QgsRectangle extent = mapCanvas->extent(); long epsgGlobe = 4326; QgsCoordinateReferenceSystem globeCrs; globeCrs.createFromOgcWmsCrs( QString( "EPSG:%1" ).arg( epsgGlobe ) ); // transform extent to WGS84 if ( mapSettings.destinationCrs().authid().compare( QString( "EPSG:%1" ).arg( epsgGlobe ), Qt::CaseInsensitive ) != 0 ) { QgsCoordinateReferenceSystem srcCRS( mapSettings.destinationCrs() ); QgsCoordinateTransform* coordTransform = new QgsCoordinateTransform( srcCRS, globeCrs ); extent = coordTransform->transformBoundingBox( extent ); delete coordTransform; } osgEarth::Util::EarthManipulator* manip = dynamic_cast<osgEarth::Util::EarthManipulator*>( mOsgViewer->getCameraManipulator() ); //rotate earth to north and perpendicular to camera manip->setRotation( osg::Quat() ); QgsDistanceArea dist; dist.setSourceCrs( globeCrs ); dist.setEllipsoidalMode( true ); dist.setEllipsoid( "WGS84" ); QgsPoint ll = QgsPoint( extent.xMinimum(), extent.yMinimum() ); QgsPoint ul = QgsPoint( extent.xMinimum(), extent.yMaximum() ); double height = dist.measureLine( ll, ul ); //camera viewing angle double viewAngle = 30; //camera distance double distance = height / tan( viewAngle * osg::PI / 180 ); //c = b*cotan(B(rad)) OE_NOTICE << "map extent: " << height << " camera distance: " << distance << std::endl; osgEarth::Util::Viewpoint viewpoint( osg::Vec3d( extent.center().x(), extent.center().y(), 0.0 ), 0.0, -90.0, distance ); manip->setViewpoint( viewpoint, 4.0 ); }
double QgsComposerScaleBar::mapWidth() const { if ( !mComposerMap ) { return 0.0; } QgsRectangle composerMapRect = *( mComposerMap->currentMapExtent() ); if ( mUnits == MapUnits ) { return composerMapRect.width(); } else { QgsDistanceArea da; da.setEllipsoidalMode( mComposition->mapSettings().hasCrsTransformEnabled() ); da.setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() ); da.setEllipsoid( mComposition->project()->ellipsoid() ); QgsUnitTypes::DistanceUnit units = QgsUnitTypes::DistanceMeters; double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ), units ); switch ( mUnits ) { case QgsComposerScaleBar::Feet: measure /= QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceFeet, units ); break; case QgsComposerScaleBar::NauticalMiles: measure /= QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceNauticalMiles, units ); break; case QgsComposerScaleBar::Meters: measure /= QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceMeters, units ); break; case QgsComposerScaleBar::MapUnits: //avoid warning break; } return measure; } }
void QgsBullsEyeWidget::createLayer( QString layerName ) { if ( layerName.isEmpty() ) { layerName = QInputDialog::getText( this, tr( "Layer Name" ), tr( "Enter name of new layer:" ) ); } if ( !layerName.isEmpty() ) { QgsDistanceArea da; da.setEllipsoid( "WGS84" ); da.setEllipsoidalMode( true ); da.setSourceCrs( mCanvas->mapSettings().destinationCrs() ); QgsRectangle extent = mCanvas->extent(); double extentHeight = da.measureLine( QgsPoint( extent.center().x(), extent.yMinimum() ), QgsPoint( extent.center().x(), extent.yMaximum() ) ); double interval = 0.5 * extentHeight * QGis::fromUnitToUnitFactor( QGis::Meters, QGis::NauticalMiles ) / 6; // Half height divided by nr rings+1, in nm QgsBullsEyeLayer* bullEyeLayer = new QgsBullsEyeLayer( layerName ); bullEyeLayer->setup( mCanvas->extent().center(), mCanvas->mapSettings().destinationCrs(), 5, interval, 45 ); QgsMapLayerRegistry::instance()->addMapLayer( bullEyeLayer ); mLayerTreeView->setCurrentLayer( bullEyeLayer ); } }
void TestQgsDistanceArea::basic() { QgsPoint p1( 1.0, 3.0 ), p2( -2.0, -1.0 ); QgsDistanceArea daA; double resultA, resultB, resultC; daA.setEllipsoid( GEO_NONE ); resultA = daA.measureLine( p1, p2 ); QCOMPARE( resultA, 5.0 ); // Now, on an ellipsoid. Always less? daA.setSourceCrs( 3006 ); daA.setEllipsoid( "WGS84" ); daA.setEllipsoidalMode( true ); resultA = daA.measureLine( p1, p2 ); QVERIFY( resultA < 5.0 ); // Test copy constructor QgsDistanceArea daB( daA ); resultB = daB.measureLine( p1, p2 ); QCOMPARE( resultA, resultB ); // Different Ellipsoid daB.setEllipsoid( "WGS72" ); resultB = daB.measureLine( p1, p2 ); QVERIFY( ! qFuzzyCompare( resultA, resultB ) ); // Test assignment QSharedPointer<QgsDistanceArea> daC( new QgsDistanceArea ); *daC = daB; resultC = daC->measureLine( p1, p2 ); QCOMPARE( resultB, resultC ); // Use parameter setting of ellipsoid radii (from WGS72 ) daA.setEllipsoid( 6378135.0, 6378135.0 - ( 6378135.0 / 298.26 ) ); resultA = daA.measureLine( p1, p2 ); QCOMPARE( resultA, resultB ); }
void TestQgsDistanceArea::measureUnits() { //test regression #13610 QgsDistanceArea calc; calc.setEllipsoidalMode( false ); calc.setEllipsoid( "NONE" ); calc.setSourceCrs( 254L ); QGis::UnitType units; QgsPoint p1( 1341683.9854275715, 408256.9562717728 ); QgsPoint p2( 1349321.7807031618, 408256.9562717728 ); double result = calc.measureLine( p1, p2, units ); //no OTF, result will be in CRS unit (feet) QCOMPARE( units, QGis::Feet ); QVERIFY( qgsDoubleNear( result, 7637.7952755903825, 0.001 ) ); calc.setEllipsoidalMode( true ); calc.setEllipsoid( "WGS84" ); result = calc.measureLine( p1, p2, units ); //OTF, result will be in meters QCOMPARE( units, QGis::Meters ); QVERIFY( qgsDoubleNear( result, 2328.0988253106957, 0.001 ) ); }
QgsAttributeActionPropertiesDialog::QgsAttributeActionPropertiesDialog( QgsAction::ActionType type, const QString& description, const QString& shortTitle, const QString& iconPath, const QString& actionText, bool capture, bool showInAttributeTable, QgsVectorLayer* layer, QWidget* parent ) : QDialog( parent ) , mLayer( layer ) { setupUi( this ); mActionType->setCurrentIndex( type ); mActionName->setText( description ); mShortTitle->setText( shortTitle ); mActionIcon->setText( iconPath ); mIconPreview->setPixmap( QPixmap( iconPath ) ); mActionText->setText( actionText ); mCaptureOutput->setChecked( capture ); mShowInAttributeTable->setChecked( showInAttributeTable ); // display the expression builder QgsExpressionContext context; context << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope() << QgsExpressionContextUtils::layerScope( mLayer ); QgsDistanceArea myDa; myDa.setSourceCrs( mLayer->crs().srsid() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->ellipsoid() ); mFieldExpression->setLayer( mLayer ); mFieldExpression->setGeomCalculator( myDa ); connect( mBrowseButton, SIGNAL( clicked( bool ) ), this, SLOT( browse() ) ); connect( mInsertFieldOrExpression, SIGNAL( clicked( bool ) ), this, SLOT( insertExpressionOrField() ) ); connect( mActionName, SIGNAL( textChanged( QString ) ), this, SLOT( updateButtons() ) ); connect( mActionText, SIGNAL( textChanged() ), this, SLOT( updateButtons() ) ); connect( mChooseIconButton, SIGNAL( clicked( bool ) ), this, SLOT( chooseIcon() ) ); updateButtons(); }
QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeature *feature, QgsMapLayer *layer, const QgsPoint& layerPoint ) { // Calculate derived attributes and insert: // measure distance or area depending on geometry type QMap< QString, QString > derivedAttributes; // init distance/area calculator QString ellipsoid = QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ); QgsDistanceArea calc; calc.setEllipsoidalMode( mCanvas->hasCrsTransformEnabled() ); calc.setEllipsoid( ellipsoid ); calc.setSourceCrs( layer->crs().srsid() ); QgsWKBTypes::Type wkbType = QgsWKBTypes::NoGeometry; QGis::GeometryType geometryType = QGis::NoGeometry; QgsVertexId vId; QgsPointV2 closestPoint; if ( feature->constGeometry() ) { geometryType = feature->constGeometry()->type(); wkbType = feature->constGeometry()->geometry()->wkbType(); //find closest vertex to clicked point closestPoint = QgsGeometryUtils::closestVertex( *feature->constGeometry()->geometry(), QgsPointV2( layerPoint.x(), layerPoint.y() ), vId ); } if ( QgsWKBTypes::isMultiType( wkbType ) ) { QString str = QLocale::system().toString( static_cast<QgsGeometryCollectionV2*>( feature->constGeometry()->geometry() )->numGeometries() ); derivedAttributes.insert( tr( "Parts" ), str ); str = QLocale::system().toString( vId.part + 1 ); derivedAttributes.insert( tr( "Part number" ), str ); } if ( geometryType == QGis::Line ) { const QgsPolyline &pline = feature->constGeometry()->asPolyline(); double dist = calc.measureLength( feature->constGeometry() ); QGis::UnitType myDisplayUnits; convertMeasurement( calc, dist, myDisplayUnits, false ); QString str = calc.textUnit( dist, 3, myDisplayUnits, false ); // dist and myDisplayUnits are out params derivedAttributes.insert( tr( "Length" ), str ); str = QLocale::system().toString( pline.size() ); derivedAttributes.insert( tr( "Vertices" ), str ); //add details of closest vertex to identify point closestVertexAttributes( *feature->constGeometry()->geometry(), vId, layer, derivedAttributes ); if ( QgsWKBTypes::flatType( wkbType ) == QgsWKBTypes::LineString ) { // Add the start and end points in as derived attributes QgsPoint pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, pline.first() ); str = QLocale::system().toString( pnt.x(), 'g', 10 ); derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str ); str = QLocale::system().toString( pnt.y(), 'g', 10 ); derivedAttributes.insert( tr( "firstY" ), str ); pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, pline.last() ); str = QLocale::system().toString( pnt.x(), 'g', 10 ); derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str ); str = QLocale::system().toString( pnt.y(), 'g', 10 ); derivedAttributes.insert( tr( "lastY" ), str ); } } else if ( geometryType == QGis::Polygon ) { double area = calc.measureArea( feature->constGeometry() ); double perimeter = calc.measurePerimeter( feature->constGeometry() ); QGis::UnitType myDisplayUnits; convertMeasurement( calc, area, myDisplayUnits, true ); // area and myDisplayUnits are out params QString str = calc.textUnit( area, 3, myDisplayUnits, true ); derivedAttributes.insert( tr( "Area" ), str ); convertMeasurement( calc, perimeter, myDisplayUnits, false ); // perimeter and myDisplayUnits are out params str = calc.textUnit( perimeter, 3, myDisplayUnits, false ); derivedAttributes.insert( tr( "Perimeter" ), str ); str = QLocale::system().toString( feature->constGeometry()->geometry()->nCoordinates() ); derivedAttributes.insert( tr( "Vertices" ), str ); //add details of closest vertex to identify point closestVertexAttributes( *feature->constGeometry()->geometry(), vId, layer, derivedAttributes ); } else if ( geometryType == QGis::Point && QgsWKBTypes::flatType( wkbType ) == QgsWKBTypes::Point ) { // Include the x and y coordinates of the point as a derived attribute QgsPoint pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, feature->constGeometry()->asPoint() ); QString str = QLocale::system().toString( pnt.x(), 'g', 10 ); derivedAttributes.insert( "X", str ); str = QLocale::system().toString( pnt.y(), 'g', 10 ); derivedAttributes.insert( "Y", str ); if ( QgsWKBTypes::hasZ( wkbType ) ) { str = QLocale::system().toString( static_cast<QgsPointV2*>( feature->constGeometry()->geometry() )->z(), 'g', 10 ); derivedAttributes.insert( "Z", str ); } if ( QgsWKBTypes::hasM( wkbType ) ) { str = QLocale::system().toString( static_cast<QgsPointV2*>( feature->constGeometry()->geometry() )->m(), 'g', 10 ); derivedAttributes.insert( "M", str ); } } return derivedAttributes; }
QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeature *feature, QgsMapLayer *layer ) { // Calculate derived attributes and insert: // measure distance or area depending on geometry type QMap< QString, QString > derivedAttributes; // init distance/area calculator QString ellipsoid = QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ); QgsDistanceArea calc; calc.setEllipsoidalMode( mCanvas->hasCrsTransformEnabled() ); calc.setEllipsoid( ellipsoid ); calc.setSourceCrs( layer->crs().srsid() ); QGis::WkbType wkbType = QGis::WKBNoGeometry; QGis::GeometryType geometryType = QGis::NoGeometry; if ( feature->geometry() ) { geometryType = feature->geometry()->type(); wkbType = feature->geometry()->wkbType(); } if ( geometryType == QGis::Line ) { double dist = calc.measure( feature->geometry() ); QGis::UnitType myDisplayUnits; convertMeasurement( calc, dist, myDisplayUnits, false ); QString str = calc.textUnit( dist, 3, myDisplayUnits, false ); // dist and myDisplayUnits are out params derivedAttributes.insert( tr( "Length" ), str ); if ( wkbType == QGis::WKBLineString || wkbType == QGis::WKBLineString25D ) { // Add the start and end points in as derived attributes QgsPoint pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, feature->geometry()->asPolyline().first() ); str = QLocale::system().toString( pnt.x(), 'g', 10 ); derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str ); str = QLocale::system().toString( pnt.y(), 'g', 10 ); derivedAttributes.insert( tr( "firstY" ), str ); pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, feature->geometry()->asPolyline().last() ); str = QLocale::system().toString( pnt.x(), 'g', 10 ); derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str ); str = QLocale::system().toString( pnt.y(), 'g', 10 ); derivedAttributes.insert( tr( "lastY" ), str ); } } else if ( geometryType == QGis::Polygon ) { double area = calc.measure( feature->geometry() ); double perimeter = calc.measurePerimeter( feature->geometry() ); QGis::UnitType myDisplayUnits; convertMeasurement( calc, area, myDisplayUnits, true ); // area and myDisplayUnits are out params QString str = calc.textUnit( area, 3, myDisplayUnits, true ); derivedAttributes.insert( tr( "Area" ), str ); convertMeasurement( calc, perimeter, myDisplayUnits, false ); // perimeter and myDisplayUnits are out params str = calc.textUnit( perimeter, 3, myDisplayUnits, false ); derivedAttributes.insert( tr( "Perimeter" ), str ); } else if ( geometryType == QGis::Point && ( wkbType == QGis::WKBPoint || wkbType == QGis::WKBPoint25D ) ) { // Include the x and y coordinates of the point as a derived attribute QgsPoint pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, feature->geometry()->asPoint() ); QString str = QLocale::system().toString( pnt.x(), 'g', 10 ); derivedAttributes.insert( "X", str ); str = QLocale::system().toString( pnt.y(), 'g', 10 ); derivedAttributes.insert( "Y", str ); } return derivedAttributes; }
QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeature *feature, QgsMapLayer *layer, const QgsPoint& layerPoint ) { // Calculate derived attributes and insert: // measure distance or area depending on geometry type QMap< QString, QString > derivedAttributes; // init distance/area calculator QString ellipsoid = QgsProject::instance()->ellipsoid(); QgsDistanceArea calc; calc.setEllipsoidalMode( mCanvas->hasCrsTransformEnabled() ); calc.setEllipsoid( ellipsoid ); calc.setSourceCrs( layer->crs().srsid() ); QgsWkbTypes::Type wkbType = QgsWkbTypes::NoGeometry; QgsWkbTypes::GeometryType geometryType = QgsWkbTypes::NullGeometry; QgsVertexId vId; QgsPointV2 closestPoint; if ( feature->hasGeometry() ) { geometryType = feature->geometry().type(); wkbType = feature->geometry().geometry()->wkbType(); //find closest vertex to clicked point closestPoint = QgsGeometryUtils::closestVertex( *feature->geometry().geometry(), QgsPointV2( layerPoint.x(), layerPoint.y() ), vId ); } if ( QgsWkbTypes::isMultiType( wkbType ) ) { QString str = QLocale::system().toString( static_cast<const QgsGeometryCollection*>( feature->geometry().geometry() )->numGeometries() ); derivedAttributes.insert( tr( "Parts" ), str ); str = QLocale::system().toString( vId.part + 1 ); derivedAttributes.insert( tr( "Part number" ), str ); } if ( geometryType == QgsWkbTypes::LineGeometry ) { double dist = calc.measureLength( feature->geometry() ); dist = calc.convertLengthMeasurement( dist, displayDistanceUnits() ); QString str = formatDistance( dist ); derivedAttributes.insert( tr( "Length" ), str ); const QgsCurve* curve = dynamic_cast< const QgsCurve* >( feature->geometry().geometry() ); if ( curve ) { str = QLocale::system().toString( curve->nCoordinates() ); derivedAttributes.insert( tr( "Vertices" ), str ); //add details of closest vertex to identify point closestVertexAttributes( *curve, vId, layer, derivedAttributes ); // Add the start and end points in as derived attributes QgsPoint pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPoint( curve->startPoint().x(), curve->startPoint().y() ) ); str = formatXCoordinate( pnt ); derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str ); str = formatYCoordinate( pnt ); derivedAttributes.insert( tr( "firstY" ), str ); pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPoint( curve->endPoint().x(), curve->endPoint().y() ) ); str = formatXCoordinate( pnt ); derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str ); str = formatYCoordinate( pnt ); derivedAttributes.insert( tr( "lastY" ), str ); } } else if ( geometryType == QgsWkbTypes::PolygonGeometry ) { double area = calc.measureArea( feature->geometry() ); area = calc.convertAreaMeasurement( area, displayAreaUnits() ); QString str = formatArea( area ); derivedAttributes.insert( tr( "Area" ), str ); double perimeter = calc.measurePerimeter( feature->geometry() ); perimeter = calc.convertLengthMeasurement( perimeter, displayDistanceUnits() ); str = formatDistance( perimeter ); derivedAttributes.insert( tr( "Perimeter" ), str ); str = QLocale::system().toString( feature->geometry().geometry()->nCoordinates() ); derivedAttributes.insert( tr( "Vertices" ), str ); //add details of closest vertex to identify point closestVertexAttributes( *feature->geometry().geometry(), vId, layer, derivedAttributes ); } else if ( geometryType == QgsWkbTypes::PointGeometry && QgsWkbTypes::flatType( wkbType ) == QgsWkbTypes::Point ) { // Include the x and y coordinates of the point as a derived attribute QgsPoint pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, feature->geometry().asPoint() ); QString str = formatXCoordinate( pnt ); derivedAttributes.insert( "X", str ); str = formatYCoordinate( pnt ); derivedAttributes.insert( "Y", str ); if ( QgsWkbTypes::hasZ( wkbType ) ) { str = QLocale::system().toString( static_cast<const QgsPointV2*>( feature->geometry().geometry() )->z(), 'g', 10 ); derivedAttributes.insert( "Z", str ); } if ( QgsWkbTypes::hasM( wkbType ) ) { str = QLocale::system().toString( static_cast<const QgsPointV2*>( feature->geometry().geometry() )->m(), 'g', 10 ); derivedAttributes.insert( "M", str ); } } return derivedAttributes; }
void QgsFieldCalculator::accept() { // Set up QgsDistanceArea each time we (re-)calculate QgsDistanceArea myDa; myDa.setSourceCrs( mVectorLayer->crs().srsid() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); QString calcString = builder->expressionText(); QgsExpression exp( calcString ); exp.setGeomCalculator( myDa ); if ( !mVectorLayer || !mVectorLayer->isEditable() ) return; if ( ! exp.prepare( mVectorLayer->pendingFields() ) ) { QMessageBox::critical( 0, tr( "Evaluation error" ), exp.evalErrorString() ); return; } QApplication::setOverrideCursor( Qt::WaitCursor ); mVectorLayer->beginEditCommand( "Field calculator" ); //update existing field if ( mUpdateExistingGroupBox->isChecked() || !mNewFieldGroupBox->isEnabled() ) { QMap<QString, int>::const_iterator fieldIt = mFieldMap.find( mExistingFieldComboBox->currentText() ); if ( fieldIt != mFieldMap.end() ) { mAttributeId = fieldIt.value(); } } else { //create new field QgsField newField( mOutputFieldNameLineEdit->text(), ( QVariant::Type ) mOutputFieldTypeComboBox->itemData( mOutputFieldTypeComboBox->currentIndex(), Qt::UserRole ).toInt(), mOutputFieldTypeComboBox->itemData( mOutputFieldTypeComboBox->currentIndex(), Qt::UserRole + 1 ).toString(), mOutputFieldWidthSpinBox->value(), mOutputFieldPrecisionSpinBox->value() ); if ( !mVectorLayer->addAttribute( newField ) ) { QMessageBox::critical( 0, tr( "Provider error" ), tr( "Could not add the new field to the provider." ) ); mVectorLayer->destroyEditCommand(); return; } //get index of the new field const QgsFields& fields = mVectorLayer->pendingFields(); for ( int idx = 0; idx < fields.count(); ++idx ) { if ( fields[idx].name() == mOutputFieldNameLineEdit->text() ) { mAttributeId = idx; break; } } if ( ! exp.prepare( mVectorLayer->pendingFields() ) ) { QMessageBox::critical( 0, tr( "Evaluation error" ), exp.evalErrorString() ); return; } } if ( mAttributeId == -1 ) { mVectorLayer->destroyEditCommand(); QApplication::restoreOverrideCursor(); return; } //go through all the features and change the new attribute QgsFeature feature; bool calculationSuccess = true; QString error; bool onlySelected = mOnlyUpdateSelectedCheckBox->isChecked(); QgsFeatureIds selectedIds = mVectorLayer->selectedFeaturesIds(); bool useGeometry = exp.needsGeometry(); int rownum = 1; bool newField = !mUpdateExistingGroupBox->isChecked(); QVariant emptyAttribute; if ( newField ) emptyAttribute = QVariant( mVectorLayer->pendingFields()[mAttributeId].type() ); QgsFeatureIterator fit = mVectorLayer->getFeatures( QgsFeatureRequest().setFlags( useGeometry ? QgsFeatureRequest::NoFlags : QgsFeatureRequest::NoGeometry ) ); while ( fit.nextFeature( feature ) ) { if ( onlySelected ) { if ( !selectedIds.contains( feature.id() ) ) { continue; } } exp.setCurrentRowNumber( rownum ); QVariant value = exp.evaluate( &feature ); if ( exp.hasEvalError() ) { calculationSuccess = false; error = exp.evalErrorString(); break; } else { mVectorLayer->changeAttributeValue( feature.id(), mAttributeId, value, newField ? emptyAttribute : feature.attributes().value( mAttributeId ) ); } rownum++; } QApplication::restoreOverrideCursor(); if ( !calculationSuccess ) { QMessageBox::critical( 0, tr( "Error" ), tr( "An error occured while evaluating the calculation string:\n%1" ).arg( error ) ); mVectorLayer->destroyEditCommand(); return; } mVectorLayer->endEditCommand(); QDialog::accept(); }
QgsFieldCalculator::QgsFieldCalculator( QgsVectorLayer* vl ) : QDialog() , mVectorLayer( vl ) , mAttributeId( -1 ) { setupUi( this ); if ( !vl ) return; builder->setLayer( vl ); builder->loadFieldNames(); populateFields(); populateOutputFieldTypes(); connect( builder, SIGNAL( expressionParsed( bool ) ), this, SLOT( setOkButtonState() ) ); QgsDistanceArea myDa; myDa.setSourceCrs( vl->crs().srsid() ); myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() ); myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); builder->setGeomCalculator( myDa ); //default values for field width and precision mOutputFieldWidthSpinBox->setValue( 10 ); mOutputFieldPrecisionSpinBox->setValue( 3 ); if ( vl->providerType() == "ogr" && vl->storageType() == "ESRI Shapefile" ) { mOutputFieldNameLineEdit->setMaxLength( 10 ); } mUpdateExistingGroupBox->setEnabled( vl->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ); mNewFieldGroupBox->setEnabled( vl->dataProvider()->capabilities() & QgsVectorDataProvider::AddAttributes ); Q_ASSERT( mNewFieldGroupBox->isEnabled() || mUpdateExistingGroupBox->isEnabled() ); if ( mNewFieldGroupBox->isEnabled() ) { mNewFieldGroupBox->setChecked( true ); } else { mNewFieldGroupBox->setToolTip( tr( "Not available for layer" ) ); mUpdateExistingGroupBox->setChecked( true ); mUpdateExistingGroupBox->setCheckable( false ); } if ( mUpdateExistingGroupBox->isEnabled() ) { mUpdateExistingGroupBox->setChecked( !mNewFieldGroupBox->isEnabled() ); } else { mUpdateExistingGroupBox->setToolTip( tr( "Not available for layer" ) ); mNewFieldGroupBox->setChecked( true ); mNewFieldGroupBox->setCheckable( false ); } mOnlyUpdateSelectedCheckBox->setChecked( vl->selectedFeaturesIds().size() > 0 ); }