• QGis C++ 开发之图层分类显示


    开发环境:Win10 + VS2010 + Qt 4.8.6 + QGis 2.14.4

    简单介绍下如何用C++方式实现QGis中图层分类显示的方法。

    要实现图层的分类显示主要会用到QgsCategorizedSymbolRendererV2类,这个类是一个简单的符号分类渲染器,该类是从QgsFeatureRendererV2继承而来,大家可以看下帮助文档中的截图:

    wps5E79.tmp

    QgsCategorizedSymbolRendererV2是其中一个子类,其他还有几个类似的子类,而这些子类的渲染方式就是对应的QGis中的几种不同的分类方式:

    wps5E8A.tmp

    所以如果掌握了其中一种分类方式的用法,其他几种都是大同小异。下面要介绍的就是上图中的第3种方式,用法简单,但是也是平时用得最多的一种方式。

    1、先说下如何简单的根据指定图层字段创建分类。先上一小段代码,再来慢慢说:

      1 	QgsCategoryList cats;
      2 	QgsFeature f;
      3 	QgsFeatureIterator it = mLayer->getFeatures();
      4 	while (it.nextFeature(f))
      5 
      6 		cats << QgsRendererCategoryV2(f.attribute("编号"),
      7 		unlinkedSymbolV2(), f.attribute("编号").toString());
      8 	}
      9 
     10 	mLayer->setRendererV2( new QgsCategorizedSymbolRendererV2("编号", cats) );

    说明下mLyaer是准备处理的一个有效的QgsVectorLayer对象。

    先看最后一句,通过图层的setRendererV2(QgsFeatureRendererV2*)便可以修改该图层的渲染方式,我们的目的就达到了,不过要详细说下传递的参数,要传递的参数就是上面提到的从QgsFeatureRendererV2继承而来的渲染器子类,我是直接通过两个参数来new了一个QgsCategorizedSymbolRendererV2对象:

    第一个参数是图层中已有的字段名称,这里我使用矢量图层中叫”编号”的字段来进行分类;

    第二个参数是一个QgsCategoryList对象,它其实是一个别名,本质上是QList<QgsRendererCategoryV2>,这个列表里保存的是与字段内容相对应的对象。QgsRendererCategoryV2是用于管理每个分类对象符号的类,通过一个图来看比较好理解,下图中显示了3种分类,每个分类就是一个单独的QgsRendererCategoryV2,它所显示的名称、颜色、符号等等都是通过QgsRendererCategoryV2来管理的。

    image

    接着看上面在while循环中我通过遍历图层中的要素,创建QgsRendererCategoryV2对象,并保存到List中,第一个参数是设置对象的值,直接返回图层中“编号”字段的值来填充;第三个参数是设置一个显示的标签,我直接就使用与第一个参数相同的值来设置;第二个参数是一个指向QgsSymbolV2的对象,该类主要用于管理符号,显示的颜色、符号、透明度这些就是通过这个参数来设置,这里我是同过一个单独的函数来返回这个对象,这个unlinkedSymbolV2()函数内容如下:

      1 QgsSymbolV2* unlinkedSymbolV2()
      2 {
      3 	QgsSymbolV2* mUnlinkedSymbolV2;
      4 
      5 	// 获得缺省的符号
      6 	mUnlinkedSymbolV2 = QgsSymbolV2::defaultSymbol(mLayer->geometryType());
      7 
      8 	// 设置透明度与颜色
      9 	mUnlinkedSymbolV2->setAlpha(0.5);
     10 	mUnlinkedSymbolV2->setColor(cUnlinked);
     11 
     12 	return mLinkedSymbolV2->clone();
     13 }
     14 

    这个符号类提供一个静态defaultSymbol函数可返回一个默认的符号对象,传入一个几何类型以返回对应的几何类型符号,然后通过setAlpha及setColor修改下符号的透明度及颜色,最后返回一个符号类指针的副本。

    这是处理前的截图:

    image

    这是处理后的截图:

    image

    2、最后再说下已经像上面分类好了,怎么进行更新。

      1  // 获得目前图层的分类样式符号渲染器
      2  QgsCategorizedSymbolRendererV2* cRenderer;
      3  cRenderer = dynamic_cast< QgsCategorizedSymbolRendererV2* >
      4  					( mLayer->rendererV2() );
      5  if (!cRenderer)
      6  {
      7  	return;
      8  }
      9  // 在渲染器中查找是否有对应的编号
     10  int index = cRenderer->categoryIndexForValue(QVariant("1"));
     11 
     12  // 更新
     13   if (-1 != index)
     14  {
     15  	cRenderer->deleteCategory(index);
     16  	cRenderer->addCategory(QgsRendererCategoryV2
     17  		(QVariant("1"), linkedSymbolV2(), "1"));
     18  }

    首先获得图层的渲染器类,如果之前图层没有进行过分类,将会得到一个空指针。

    之前我们在构造QgsRendererCategoryV2对象时不是用“编号”字段的内容设置了它的值吗,现在就可以通过categoryIndexForValue函数来返回索引,找到正确的索引后先删除原来记录,再通过addCategory添加一个新的对象进去,这里我同样通过调用一个linkedSymbolV2()返回符号,和unlinkedSymbolV2()不同的地方就是颜色改变了,所以就不贴代码了。

    更新完后还会有个小问题,会发现新添加的分类符号都显示在最后,显示顺序和之前不一样了,可以用下面这个方法按值重新排序。

      1 cRenderer->sortByValue();

    关于图层分类显示基本上就这样了,其实涉及代码不多,应该还是好理解,其他几种分类渲染方式都大同小异。

  • 相关阅读:
    各种文件的mime类型
    LeetCode_122. Best Time to Buy and Sell Stock II
    LeetCode_121. Best Time to Buy and Sell Stock
    LeetCode_119. Pascal's Triangle II
    LeetCode_118. Pascal's Triangle
    LeetCode_112. Path Sum
    LeetCode_111. Minimum Depth of Binary Tree
    LeetCode_110. Balanced Binary Tree
    LeetCode_108. Convert Sorted Array to Binary Search Tree
    LeetCode_107. Binary Tree Level Order Traversal II
  • 原文地址:https://www.cnblogs.com/yuan-long/p/6038446.html
Copyright © 2020-2023  润新知