<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      GDAL矢量數據集相關接口的資源控制問題

      1. 引言

      筆者在《使用GDAL讀寫矢量文件》這篇文章中總結了通過GDAL讀寫矢量的具體實現。不過這篇文章中并沒有談到涉及到矢量數據集相關接口的資源控制問題。具體來說,GDAL/OGR誕生的年代連C++語言本身都不是很完善(c++11之前),因此提供的C++接口往往存在申請的資源需要釋放的問題,因此在這里將其總結一下。

      2. 詳論

      2.1 數據集類GDALDataset

      矢量數據集GDALDataset對象需要通過GDALOpenEx來讀取或者更新。在不需要這個對象之后,使用GDALClose進行關閉。例如:

      GDALDataset *poDS = (GDALDataset*)GDALOpenEx(filePath, GDAL_OF_VECTOR, NULL, NULL, NULL);
      
      //...
      
      GDALClose(poDS);
      poDS = nullptr;
      

      另一方面,通過驅動類GDALDriver創建矢量數據集,不需要之后仍然使用GDALClose進行關閉。例如:

      GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("ESRI Shapefile");
      if (!driver)
      {
          printf("Get Driver ESRI Shapefile Error!\n");
          return false;
      }
      	
      GDALDataset* dataset = driver->Create(filePath, 0, 0, 0, GDT_Unknown, NULL);
      
      GDALClose(dataset);
      dataset = nullptr;
      

      理論上來說,GDALDataset對象在打開或者創建之后,使用delete進行釋放也是可以的。但是一般而言,最好使用GDAL本身提供出來的釋放接口。因為這個接口的內部實現可能并不只是delete那么簡單,可能有其他的資源釋放操作。不僅僅是GDAL,其他類庫也是同理。

      2.2 圖層類OGRLayer

      GDALDataset既可以是矢量數據集,也可以是柵格數據集。但是只有矢量數據集才能獲取或創建圖層類OGRLayer。但是無論是獲取還是創建OGRLayer,再無需使用之后,都不用再進行主動釋放了,OGRLayer對象會被GDALDataset對象托管,在GDALClose釋放數據集對象之后,圖層類OGRLayer就會隨之釋放。

      OGRLayer* poLayer = poDS->GetLayer(0);
      //獲取后無需顯式釋放OGRLayer
      
      OGRLayer* poLayer = dataset->CreateLayer("houseType", NULL, wkbPolygon, NULL);
      //創建后無需顯式釋放OGRLayer
      

      2.3 要素類OGRFeature

      要素類OGRFeature一般從圖層類OGRLayer對象中獲取或者創建,不過無論是獲取還是創建都需要進行顯式釋放。例如讀取矢量數據集時遍歷獲取要素:

      OGRFeature *poFeature;
      while ((poFeature = poLayer->GetNextFeature()) != NULL)
      {
          OGRGeometry *pGeo = poFeature->GetGeometryRef();
          //...
          OGRFeature::DestroyFeature(poFeature);
      }
      

      這里的OGRFeature::DestroyFeature(poFeature);就是GDAL提供的用于銷毀要素對象的方法。另一方面,如果是寫出數據集創建要素,比如筆者這里創建一個經緯度網格的矢量:

      for (int yi = -90; yi < 90; ++yi) {
          for (int xi = -180; xi < 180; ++xi) {    
            OGRFeature poFeature(poLayer->GetLayerDefn());
      
            OGRLinearRing ogrRing;
            ogrRing.addPoint(xi, yi);
            ogrRing.addPoint(xi + 1, yi);
            ogrRing.addPoint(xi + 1, yi + 1);
            ogrRing.addPoint(xi, yi + 1);
            ogrRing.closeRings();
      
            OGRPolygon polygon;
            polygon.addRing(&ogrRing);
            poFeature.SetGeometry(&polygon);
      
            if (poLayer->CreateFeature(&poFeature) != OGRERR_NONE) {
              printf("Failed to create feature in shapefile.\n");
              return false;
            }
          }
        }
      

      OGRFeature使用的是值對象,在超出作用域之后會自動銷毀。經過驗證筆者這樣寫并沒有問題,可以推斷OGRLayer對于OGRFeature對象的管理應該是采用的深拷貝方式,并且會托管這個拷貝后的OGRFeature對象。

      2.4 幾何類OGRGeometry

      幾何類OGRGeometry使用了C++類的繼承和多態特性,本身其是一個基類,但是繼承出了如OGRLinearRing、OGRPolygon等子類來表達點線面多種要素幾何類型。因此GDAL提供了一個工廠類來創建和銷毀,這是一種非常經典的設計模式:

      OGRGeometry* poGeom = OGRGeometryFactory::createGeometry(wkbPoint);
      // 使用完 poGeom 后釋放它
      OGRGeometryFactory::destroyGeometry(poGeom);
      

      也就是OGRGeometryFactory::createGeometry和OGRGeometryFactory::destroyGeometry需要成對出現。不過筆者認為如果不是為了多態表達,直接使用值對象更加方便,如第2.3節中的示例所示。

      另外,OGRGeometry對象是需要放置到OGRFeature對象中的,因此OGRFeature提供了兩個接口:

      1. OGRErr SetGeometryDirectly(OGRGeometry*):淺拷貝OGRGeometry對象,OGRFeature對象直接托管OGRGeometry對象的所有權。
      2. OGRErr SetGeometry(const OGRGeometry*):深拷貝OGRGeometry對象,OGRFeature對象托管OGRGeometry拷貝對象的所有權。

      另外,幾何類之間的相互引用也是如此,如第2.3節中的示例所示,多邊形增加環也有兩個接口:

      1. addRingDirectly() 淺拷貝OGRLinearRing對象,OGRPolygon對象直接托管OGRLinearRing對象的所有權。
      2. addRing()深拷貝OGRLinearRing對象,OGRPolygon對象托管OGRLinearRing拷貝對象的所有權。

      也就是一般而言,GDAL通常使用Directly后綴的函數接口來表達對原幾何對象的托管。

      3. 其他

      可以看到,GDAL的資源控制方面還是有點混亂的,有的要顯式釋放,有的又可以托管,有的干脆提供了兩個接口。據說新的GDAL版本引入了很多新的C++特性,估計資源控制的邏輯要清晰一點。另外,我們也可以主動使用一些新的C++特性來避免資源控制需要主動釋放的問題。例如使用智能指針,配合自定義刪除器來銷毀OGRFeature對象,如下例所示:

      // 獲取第一個圖層
      OGRLayer* poLayer = poDS->GetLayer(0);
      if (poLayer == nullptr) {
          std::cerr << "Failed to get the layer." << std::endl;
          GDALClose(poDS);
          return -1;
      }
      
      // 自定義刪除器用于銷毀 OGRFeature
      auto featureDeleter = [](OGRFeature* poFeature) {
          OGRFeature::DestroyFeature(poFeature);
      };
      
      // 遍歷圖層中的要素
      poLayer->ResetReading();
      std::unique_ptr<OGRFeature, decltype(featureDeleter)> poFeature(nullptr, featureDeleter);
      
      while ((poFeature.reset(poLayer->GetNextFeature())), poFeature) {
          // 獲取幾何體
          OGRGeometry* poGeometry = poFeature->GetGeometryRef();
          if (poGeometry != nullptr) {
              // 輸出幾何體的WKT表示
              char* pszWKT = nullptr;
              poGeometry->exportToWkt(&pszWKT);
              std::cout << "Geometry: " << pszWKT << std::endl;
              CPLFree(pszWKT);  // 釋放WKT字符串
          }
      }
      
      posted @ 2025-02-04 22:00  charlee44  閱讀(230)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲综合小说另类图片五月天| 国产精品大全中文字幕| 亚洲精品中文综合第一页| 日韩亚洲中文图片小说| 欧美熟妇xxxxx欧美老妇不卡 | 亚洲美女厕所偷拍美女尿尿 | 国产成人一区二区不卡| 牲欲强的熟妇农村老妇女视频| 亚洲国产区男人本色vr| 国产免费午夜福利在线播放 | 久久久久人妻精品一区三寸| 国产亚洲无日韩乱码| 日韩AV高清在线看片| 国内精品伊人久久久久影院对白| 女子spa高潮呻吟抽搐| 中文字幕乱码中文乱码毛片| 亚洲性日韩精品一区二区| 色多多性虎精品无码av| 色吊a中文字幕一二三区| 亚洲精品中文字幕尤物综合| 乱人伦中文视频在线| 老司机亚洲精品一区二区| 国产精品七七在线播放| 爆乳女仆高潮在线观看| 9久9久热精品视频在线观看| 舞阳县| 久久中文字幕国产精品| 四虎影视一区二区精品| 成人无码午夜在线观看| 成人区人妻精品一区二区| 无码精品国产va在线观看| 激情综合网激情国产av| 又爽又黄又无遮挡的视频 | 精品无码成人片一区二区| 金昌市| 国产成人啪精品午夜网站| 国产精品一二二区视在线| 日夜啪啪一区二区三区| 一区二区亚洲人妻精品| 免费观看全黄做爰大片| 欧美拍拍视频免费大全|