GDAL不支持創建PCIDSK的面狀矢量格式

最近在使用GDAL創建PCIDSK格式的矢量數據,發現創建點和線的矢量數據都沒問題,創建面狀的只有屬性表沒有圖形。在GDAL官網說明也寫的是支持的,地址爲:http://www.gdal.org/frmt_pcidsk.html。

實在沒辦法,翻看GDAL源碼才發現,SetFeature的時候,只寫了wkbPoint和wkbLineString類型,其他的加了句Debug代碼如下:

            CPLDebug( "PCIDSK", "Unsupported geometry type in SetFeature(): %s",
                      poGeometry->getGeometryName() );
這也太……沒辦法只好自己研究研究補齊了。

通過查看GDAL讀取發現,對於面狀的矢量,PCIDSK在矢量段裏面的屬性表裏面多存了一個字段,叫RingStart,類型爲IntList,用來存儲多邊形中各個環的起始點號。對於PCIDSK的矢量數據,所有的點都是存儲在一個大的數組裏面的,對於多邊形而言,可能有多個環組成,這些環裏面所有的點全部都存在一個數組中,如何來區分每個環的頂點座標,就需要通過RingStart裏面的值來進行分割。知道了存儲的原理,那麼就按照這個原理將寫多邊形的部分補上就可以了。修改後的代碼如下:

		else if( wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon )
		{
			OGRPolygon *poPoly = (OGRPolygon *) poGeometry;
			int nRingSize = poPoly->getNumInteriorRings();
			
			std::vector<PCIDSK::int32> anRingStart;
			anRingStart.resize(nRingSize+1);
			
			OGRLinearRing *poRing = NULL;
			poRing = poPoly->getExteriorRing();
			anRingStart[0] = poRing->getNumPoints();
			
			aoVertices.resize(poRing->getNumPoints());
			for(int i = 0; i < aoVertices.size(); i++ )
			{
				aoVertices[i].x = poRing->getX(i);
				aoVertices[i].y = poRing->getY(i);
				aoVertices[i].z = poRing->getZ(i);
			}

			for (int iRing=0; iRing < nRingSize; iRing++)
			{
				int nCurrentStart = aoVertices.size();
				poRing = poPoly->getInteriorRing(iRing);
				anRingStart[iRing+1] = nCurrentStart + poRing->getNumPoints();
				aoVertices.resize(nCurrentStart + poRing->getNumPoints());

				for(int i = nCurrentStart; i < aoVertices.size(); i++ )
				{
					aoVertices[i].x = poRing->getX(i-nCurrentStart);
					aoVertices[i].y = poRing->getY(i-nCurrentStart);
					aoVertices[i].z = poRing->getZ(i-nCurrentStart);
				}
			}
			
			if(iRingStartField == -1)
			{
				iRingStartField = poVecSeg->GetFieldCount();
				//poVecSeg->AddField( "RingStart", PCIDSK::FieldTypeCountedInt, "", "" );
	  			OGRFieldDefn oField( "RingStart", OFTIntegerList );
	  			//oField.SetWidth(100);
	  			CreateField( &oField );
			}

			std::vector<PCIDSK::ShapeField> aoShapeFields;
			poVecSeg->GetFields(id, aoShapeFields);

			aoShapeFields[iRingStartField].SetValue(anRingStart);
			poVecSeg->SetFields( id, aoShapeFields );
		}

修改完之後,重新編譯GDAL就可以了。

=======================修改於2015年1月9日========================

通過上面的代碼是可以生成一個面狀的pix文件,使用GDAL打開也沒問題,但是使用Focus或者MosaicTool打開的時候會造成這兩個程序崩潰,同時屬性值顯示會有一定點問題。今天再仔細查看了下讀取部分的代碼,發現對於沒有內環的多邊形,也就是說一個Feature裏面只有一個多邊形的時候,不需要寫RingStart這個屬性值,只有含油內環的時候,也就是多邊形中有內環的時候才需要,所以將上面的代碼修改爲下面的代碼:

		else if( wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon )
		{
			OGRPolygon *poPoly = (OGRPolygon *) poGeometry;
			OGRLinearRing *poRing = NULL;
			poRing = poPoly->getExteriorRing();
			
			aoVertices.resize(poRing->getNumPoints());
			for(int i = 0; i < aoVertices.size(); i++ )
			{
				aoVertices[i].x = poRing->getX(i);
				aoVertices[i].y = poRing->getY(i);
				aoVertices[i].z = poRing->getZ(i);
			}

			int nRingSize = poPoly->getNumInteriorRings();
			if(nRingSize > 0 )
			{
				std::vector<PCIDSK::int32> anRingStart;
				anRingStart.resize(nRingSize+1);
				anRingStart[0] = poRing->getNumPoints();

				for (int iRing=0; iRing < nRingSize; iRing++)
				{
					int nCurrentStart = aoVertices.size();
					poRing = poPoly->getInteriorRing(iRing);
					anRingStart[iRing+1] = nCurrentStart + poRing->getNumPoints();
					aoVertices.resize(nCurrentStart + poRing->getNumPoints());

					for(int i = nCurrentStart; i < aoVertices.size(); i++ )
					{
						aoVertices[i].x = poRing->getX(i-nCurrentStart);
						aoVertices[i].y = poRing->getY(i-nCurrentStart);
						aoVertices[i].z = poRing->getZ(i-nCurrentStart);
					}
				}
				
				if(iRingStartField == -1)
				{
					iRingStartField = poVecSeg->GetFieldCount();
					OGRFieldDefn oField( "RingStart", OFTIntegerList );
					CreateField( &oField );
				}

				std::vector<PCIDSK::ShapeField> aoShapeFields;
				poVecSeg->GetFields(id, aoShapeFields);
				aoShapeFields[iRingStartField].SetValue(anRingStart);
				poVecSeg->SetFields( id, aoShapeFields );
			}
		}
通過測試發現,這下生成的使用Foucs和MosaicTool可以正常打開,程序也不會出現崩潰的情況,但是屬性值顯示仍然有點小問題,不過已經不影響使用了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章