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()->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; }
bool QgsMapToolIdentify::identifyVectorLayer( QgsVectorLayer *layer, int x, int y ) { if ( !layer ) return false; QMap< QString, QString > attributes, derivedAttributes; QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y ); derivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() ); // load identify radius from settings QSettings settings; double identifyValue = settings.value( "/Map/identifyRadius", QGis::DEFAULT_IDENTIFY_RADIUS ).toDouble(); QString ellipsoid = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString(); if ( identifyValue <= 0.0 ) identifyValue = QGis::DEFAULT_IDENTIFY_RADIUS; int featureCount = 0; QgsFeatureList featureList; // toLayerCoordinates will throw an exception for an 'invalid' point. // For example, if you project a world map onto a globe using EPSG 2163 // and then click somewhere off the globe, an exception will be thrown. try { // create the search rectangle double searchRadius = mCanvas->extent().width() * ( identifyValue / 100.0 ); QgsRectangle r; r.setXMinimum( point.x() - searchRadius ); r.setXMaximum( point.x() + searchRadius ); r.setYMinimum( point.y() - searchRadius ); r.setYMaximum( point.y() + searchRadius ); r = toLayerCoordinates( layer, r ); layer->select( layer->pendingAllAttributesList(), r, true, true ); QgsFeature f; while ( layer->nextFeature( f ) ) featureList << QgsFeature( f ); } catch ( QgsCsException & cse ) { Q_UNUSED( cse ); // catch exception for 'invalid' point and proceed with no features found QgsDebugMsg( QString( "Caught CRS exception %1" ).arg( cse.what() ) ); } // init distance/area calculator QgsDistanceArea calc; if ( !featureList.count() == 0 ) { calc.setProjectionsEnabled( mCanvas->hasCrsTransformEnabled() ); // project? calc.setEllipsoid( ellipsoid ); calc.setSourceCrs( layer->crs().srsid() ); } QgsFeatureList::iterator f_it = featureList.begin(); for ( ; f_it != featureList.end(); ++f_it ) { featureCount++; QgsFeatureId fid = f_it->id(); QMap<QString, QString> derivedAttributes; // Calculate derived attributes and insert: // measure distance or area depending on geometry type if ( layer->geometryType() == QGis::Line ) { double dist = calc.measure( f_it->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 ( f_it->geometry()->wkbType() == QGis::WKBLineString || f_it->geometry()->wkbType() == QGis::WKBLineString25D ) { // Add the start and end points in as derived attributes str = QLocale::system().toString( f_it->geometry()->asPolyline().first().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( f_it->geometry()->asPolyline().first().y(), 'g', 10 ); derivedAttributes.insert( tr( "firstY" ), str ); str = QLocale::system().toString( f_it->geometry()->asPolyline().last().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( f_it->geometry()->asPolyline().last().y(), 'g', 10 ); derivedAttributes.insert( tr( "lastY" ), str ); } } else if ( layer->geometryType() == QGis::Polygon ) { double area = calc.measure( f_it->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 ); } else if ( layer->geometryType() == QGis::Point && ( f_it->geometry()->wkbType() == QGis::WKBPoint || f_it->geometry()->wkbType() == QGis::WKBPoint25D ) ) { // Include the x and y coordinates of the point as a derived attribute QString str; str = QLocale::system().toString( f_it->geometry()->asPoint().x(), 'g', 10 ); derivedAttributes.insert( "X", str ); str = QLocale::system().toString( f_it->geometry()->asPoint().y(), 'g', 10 ); derivedAttributes.insert( "Y", str ); } derivedAttributes.insert( tr( "feature id" ), fid < 0 ? tr( "new feature" ) : FID_TO_STRING( fid ) ); results()->addFeature( layer, *f_it, derivedAttributes ); } QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) ); return featureCount > 0; }