qgis二次开发矢量数据点选择的方法

qgis二次开发矢量数据点选择的方法


发布日期: 2015-07-20 更新日期: 2015-07-20 编辑:bukun 浏览次数: 8392

标签:

摘要: qgis的资料比较少,能找到的资料就那么几篇基本的加载图层之类的,最主要还是参考qgis本身的源码和其api文档。 qgis程序是C++和qt平台编译出来的可执行文件。 其中MapCanvas保存了一个指针指向当前的tool,tool里面有各种响应鼠标等事件。...

qgis的资料比较少,能找到的资料就那么几篇基本的加载图层之类的,最主要还是参考qgis本身的源码和其api文档。

qgis程序是C++和qt平台编译出来的可执行文件。

其中MapCanvas保存了一个指针指向当前的tool,tool里面有各种响应鼠标等事件。

MapCanvas中的响应系统鼠标事件,调用tool的事件

其中鼠标Middle单击事件,被定义为pan(tool)的事件

tool可以setAction,也可以设置按键。(效果应该等同于Action的trigger信号绑定MapCanvas,设置mapcanvas的当前tool。)还可以设置cursor设置鼠标的形状(手型)

所以在知道qgis的tool功能的基础上找到源码中的selecttool,将selecttool移植到自己的程序中。

注意:这移植的过程中,也出现了一些问题,以为可以调用qgisapp的库进行移植,但是移植过程中出现了一系列的错误。所以最后还是只调用qgis的核心库

//QgsVectorLayer* vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( mCanvas );
//这一行的功能为选择当前的矢量图层,改成如下代码:
QgsVectorLayer* vlayer = NULL;
if ( !canvas->currentLayer()
|| ( vlayer = qobject_cast( canvas->currentLayer() ) ) == NULL )
{
QMessageBoox::information(...);}



if ( vlayer == NULL )
{
return;
}


QgsRubberBand *rubberBand = new QgsRubberBand( mCanvas, QGis::Polygon );
QRect selectRect( 0, 0, 0, 0 );
//QgsMapToolSelectUtils::expandSelectRectangle( selectRect, vlayer, e->pos() );
//这行代码的意义在于将点的范围扩大。

int boxSize = 0;
if ( vlayer->geometryType() != QGis::Polygon )
{
//if point or line use an artificial bounding box of 10x10 pixels
//to aid the user to click on a feature accurately
boxSize = 5;
}
else
{
//otherwise just use the click point for polys
boxSize = 1;
}
selectRect.setLeft( point.x() - boxSize );
selectRect.setRight( point.x() + boxSize );
selectRect.setTop( point.y() - boxSize );
selectRect.setBottom( point.y() + boxSize );
//
// QgsMapToolSelectUtils::setRubberBand( mCanvas, selectRect, &rubberBand );
const QgsMapToPixel* transform = canvas->getCoordinateTransform();
QgsPoint ll = transform->toMapCoordinates( selectRect.left(), selectRect.bottom() );
QgsPoint ur = transform->toMapCoordinates( selectRect.right(), selectRect.top() );


if ( rubberBand )
{
rubberBand->reset( QGis::Polygon );
rubberBand->addPoint( ll, false );
rubberBand->addPoint( QgsPoint( ur.x(), ll.y() ), false );
rubberBand->addPoint( ur, false );
rubberBand->addPoint( QgsPoint( ll.x(), ur.y() ), true );
}
QgsGeometry* selectGeom = rubberBand.asGeometry();
bool doDifference = e->modifiers() & Qt::ControlModifier ? true : false;
// QgsMapToolSelectUtils::setSelectFeatures( mCanvas, selectGeom, false, doDifference, true );
//这一行才是选择的功能


if ( selectGeometry->type() != QGis::Polygon )
{
return;
}
QgsVectorLayer* vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( canvas );
if ( vlayer == NULL )
{
return;
}


// toLayerCoordinates will throw an exception for any 'invalid' points in
// the rubber band.
// 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.
QgsGeometry selectGeomTrans( *selectGeometry );


if ( canvas->mapSettings().hasCrsTransformEnabled() )
{
try
{
QgsCoordinateTransform ct( canvas->mapSettings().destinationCrs(), vlayer->crs() );
selectGeomTrans.transform( ct );
}
catch ( QgsCsException &cse )
{
Q_UNUSED( cse );
// catch exception for 'invalid' point and leave existing selection unchanged
// QgsLogger::warning( "Caught CRS exception " + QString( __FILE__ ) + ": " + QString::number( __LINE__ ) );
QMessageBox::warning( canvas, QObject::tr( "CRS Exception" ),
QObject::tr( "Selection extends beyond layer's coordinate system." ) );
return;
}
}


QApplication::setOverrideCursor( Qt::WaitCursor );


QgsDebugMsg( "Selection layer: " + vlayer->name() );
QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() );
QgsDebugMsg( "doContains: " + QString( doContains ? "T" : "F" ) );
QgsDebugMsg( "doDifference: " + QString( doDifference ? "T" : "F" ) );


QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectGeomTrans.boundingBox() ).setFlags( QgsFeatureRequest::ExactIntersect ).setSubsetOfAttributes( QgsAttributeList() ) );


QgsFeatureIds newSelectedFeatures;
QgsFeature f;
QgsFeatureId closestFeatureId = 0;
bool foundSingleFeature = false;
double closestFeatureDist = std::numeric_limits::max();
while ( fit.nextFeature( f ) )
{
QgsGeometry* g = f.geometry();
//if ( doContains )
// {
if ( !selectGeomTrans.contains( g ) )
continue;
// }
// else
// {
// if ( !selectGeomTrans.intersects( g ) )
// continue;
// }
//if ( singleSelect )
// {
foundSingleFeature = true;
double distance = g->distance( selectGeomTrans );
if ( distance <= closestFeatureDist )
{
closestFeatureDist = distance;
closestFeatureId = f.id();
}
// }
// else
// {
// newSelectedFeatures.insert( f.id() );
// }
}
if ( /*singleSelect &&*/ foundSingleFeature )
{
newSelectedFeatures.insert( closestFeatureId );
}


QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() ) );


if ( doDifference )
{
QgsFeatureIds layerSelectedFeatures = vlayer->selectedFeaturesIds();


QgsFeatureIds selectedFeatures;
QgsFeatureIds deselectedFeatures;


QgsFeatureIds::const_iterator i = newSelectedFeatures.constEnd();
while ( i != newSelectedFeatures.constBegin() )
{
--i;
if ( layerSelectedFeatures.contains( *i ) )
{
deselectedFeatures.insert( *i );
}
else
{
selectedFeatures.insert( *i );
}
}


vlayer->modifySelection( selectedFeatures, deselectedFeatures );
}
else
{
vlayer->setSelectedFeatures( newSelectedFeatures );
}


QApplication::restoreOverrideCursor();
delete selectGeom;
rubberBand.reset( QGis::Polygon );

关注公众号
获取免费资源

随机推荐


Copyright © Since 2014. 开源地理空间基金会中文分会 吉ICP备05002032号

Powered by TorCMS

OSGeo 中国中心 邮件列表

问题讨论 : 要订阅或者退订列表,请点击 订阅

发言 : 请写信给: osgeo-china@lists.osgeo.org