日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于ArcSDE的影像数据管理-解决篇(转载)

發布時間:2024/9/20 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于ArcSDE的影像数据管理-解决篇(转载) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文為轉載http://www.cnblogs.com/rib06/category/56544.html
疑惑篇中簡單介紹了基于ArcSDE的影像數據管理的基本方法、策略及其缺陷。那么要想基于ArcSDE的Raster Catalog實現對影像數據的任意范圍查詢,并且在跨圖幅的情況下做到無縫拼接該怎么實現呢?
我是這樣做的。
首先說說邏輯上的思路。
問題的輸入和輸出都是很明確的。
輸入:BBox, w
說明一下,BBox是Bounding Box的縮寫,是以地理坐標表示的查詢范圍,由left, right, top和bottom四個參數組成;w為視口的大小,即最終顯示在Web上(我說過的哦,這個影像數據源包裝器是一個WebGIS項目服務器端的一部分)給用戶看的地圖窗口的大小,由width和height兩個參數組成。
輸出:與查詢范圍精確匹配的一幅w大小的jpeg圖像文件
再說明一下,jpeg圖像是經過有損壓縮的,數據量比較小,我程序中每次得到的圖像文件數據量一般在50~100K左右,在Internet上傳輸是可以接受的。這種圖像不帶坐標信息,也無法進行二次處理,就是純粹的一張圖片,很純的那種。這不太符合OGC的WCS規范,因為我現在只能提供jpeg圖像;但卻有點像WMS,如果把接口改改的話就算勉強符合。
那么根據ArcSDE中影像數據的管理和存儲方式,從邏輯上我按照以下步驟完成功能:
第一步:根據BBox與w計算顯示比例尺s;
第二步:根據s計算提取數據所在的金字塔級別l;
第三步:通過一次散列,求出與BBox相交的圖幅序列ImageList(I1, I2, I3…);
第四步:將BBox分解到ImageList中的每一個圖幅元素上成為子查詢序列subBBox(sb1, sb2, sb3…);
第五步:在l級金字塔上,通過第二次散列,在Ii上求出與sbi相交的圖塊序列TileListi(B1, B2, B3…);
第六步:提取第三步得到的全部圖塊的數據;
第七步:將第四步得到的數據還原成位圖文件
嗯,總體上就是這個樣子。下面逐步細說。
第一、二步挺簡單不用解釋,第三步開始就有問題了。
在疑惑篇中我說了,SDE認為Raster Catalog就是一“相冊”,其中存儲的影像是沒有什么關系的,更不會為它們建立什么索引結構。這樣要想實現第三步中的散列就要先為Raster Catalog中的圖幅建立索引表,這個表我建在了影像數據所在的表空間里,名字就叫IMAGEINDEX,里面為所有圖幅按照它們之間的拓撲關系建立了格網索引——每個圖幅一個行號、一個列號。但這時就又有問題了,基礎數據一共460個圖幅,全拼起來并不是一個大長方形,而是基本與目標區域邊界吻合的鋸齒形。那么若建立格網索引就必然會有一些空的地方,就是說會有一些格網號并沒有實際的圖幅與之對應。那么對于這些空的地方,我是將它們也寫入索引表,但標識其目標為0呢還是直接跳過它們不管呢?我選擇了前者。這樣,一個如下面示意圖所示的格網索引就建起來了,第一次散列的問題也就可以解決了。而第五步中的第二次散列由于SDE對每個圖幅中的圖塊是做了格網索引的(疑惑篇中有介紹),所以易于實現。

下面是最關鍵的第三到第五步,在這三步中,我要完成圖幅的去零,以支持跨幅查詢時的無縫拼接。因為我可以通過SDE API得到每個圖幅原來的大小,即未補零時的大小,還可以得到圖塊的大小,通過它們就可以算出圖幅邊緣補零部分的寬度和高度,當查詢涉及到那些帶有零元的圖塊時,我就能知道其中有效信息部分的大小,進而只讀取它們,跳過零元。但這帶來一個小問題,就是圖塊的大小出現了不均勻。為此,我采用了一種比較笨的辦法,就是讓ImageList中的每個圖幅Ii都自己記錄自己的TileListi中每個圖塊的大小。這樣在第六步提取數據和第七步恢復圖像的時候就可以按照每個圖塊的實際大小來讀寫,而那些補的零就都可以去死了。這就是我去零的基本思路。
提取每個圖塊數據時,外層循環對ImageList的遍歷順序是Z序的,而內層循環在每個圖幅內部對TileList的訪問順序也是Z序的。與之對應的,在恢復圖像的時候,在每個圖塊內部繪制像素的順序、在每個圖幅內繪制圖塊的順序、繪制圖幅的順序也都是Z序的。如下圖所示:

最后一步得到位圖還沒完,需要再稍做加工,因為它的地理范圍比BBox要大(因為提取數據的最小單位是圖塊而不是像素,這個應該好理解吧),所以要將它中間BBox對應的那一部分切出來。這還沒完,切出來的部分可能不是w大小(這是因為金字塔索引是離散的,按比例尺拿數據只能就近取金字塔中的某一級),但不會差很遠,所以還要稍微拉伸才行。這樣兩步加工之后得到的才是最終產品。
以上就是我整個思路的要點概況,其中關鍵的就在去零實現無縫拼接,不知道說清楚了沒有。其實辦法也挺初級的,疑惑篇的評論中bluntsword一下就給出解決思路了。本人比較笨,唉~~

下面再說說具體實現吧。事先說明一下,我的OOA/D經驗相當匱乏,具體解決方案給出之后大家可能會覺得十分齷齪而不堪如目,其中可能會有不計其數的違背OO原則的地方,但請大家相信這也絕非我本意。諸位如果實在看不下去想罵兩句的話就不用忍了。如果有一天我能看到某介紹設計方案的文獻上有我的設計——作為反面教材,那我也無怨無悔。不過雖然它很丑,但它在我們整個WebGIS系統中還算是比較穩定的一塊。
SDE C-API是C寫的(廢話!),其中使用了少量C++的特性,不支持我相對比較熟悉的.net,所以我選擇了VC6來實現。
這個影像數據包裝器只負責從影像數據源中抽取數據,形成圖片,并傳回給GIS服務器,所以其實它連界面都不需要,但我建了個對話框應用,上面擺一個Edit,用于輸出運行時的一些狀態信息。
為實現功能,我建了一個CMyRaster類,它的內部完成了我想要的全部事情(這是不是一個典型的“全能類”啊,好怕怕~~)。其結構如下:(由于不能貼C++代碼,所以這里暫且用C#格式的,下同)
class?CMyRaster??
{
public:
????
static?WCHAR*?ToWChar(char?*?str);?//?在GDI+中,有關字符的參數類型全部都是WCHAR類型,該函數是將傳統字符串進行轉換
????static?int?DisconnectSDE(SE_CONNECTION?*connection);?//?斷開與SDE的連接
????static?int?ConnectSDE(char?*SDE_servername,?char?*SDE_service,?char?*SDE_instance,?char?*SDE_user,?char?*SDE_password,?SE_CONNECTION?*connection);?//?連接SDE
//????這里應該提供一個ConnectSDE的重載版本用于連接SQLServer服務器
????int?GetRaster(const?SE_CONNECTION?connection,?const?_ConnectionPtr?ADOConn,?double?left,?double?right,?double?top,?double?bottom,?long?userScale,?CString?filename);?//?提取影像數據并生成圖片的核心方法
????CMyRaster();
????
virtual?~CMyRaster();

private:
????
int?m_QueryRasterRight;?//?與查詢范圍相交的圖幅序列的格網索引范圍
????int?m_QueryRasterLeft;
????
int?m_QueryRasterTop;
????
int?m_QueryRasterBottom;
????RASTER_METADATA?
*m_RastersMetadata;?//?圖幅元數據數組,核心變量????
????char?strTableName[SE_QUALIFIED_TABLE_NAME];?//?Raster?Catalog的表名????
????char?strColName[SE_MAX_COLUMN_LEN];?//?數據的列名,一般就是"IMAGE"????
????int????m_QueryPyramidLevel;?//?查詢所在的金字塔級別????
????SE_INTERPOLATION_TYPE?m_Interpolation;?//?插值的方法????
????long?*m_ScaleByLevel;?//?金字塔該級別上的比例尺????
????long?m_NumOfBands;?//?波段數
????long?m_PyramidHeight;?//?金字塔高度
????IMAGE_EXTENT?m_DefaultTileSize;?//?tile大小的預設值????
????SE_ENVELOPE?m_WholeExtent;?//?最大的全圖范圍
????int?m_UserMapWidth;?//?用戶地圖區的寬度
????int?m_UserMapHeight;?//?用戶地圖區的高度

????
int?Get_RasterMetadata_by_BBox(const?SE_CONNECTION?connection,?const?_ConnectionPtr?ADOConn,?double?left,?double?right,?double?top,?double?bottom,?long?userScale);?//?獲取SDE中raster圖層的元數據
int?Get_RasterData_from_SDE(const?SE_CONNECTION?connection,?const?_ConnectionPtr?ADOConn);?//?從數據源中提取影像數據
int?Write_to_BMP_file(double?left,?double?right,?double?top,?double?bottom,?CString?filename);?//?將影像數據恢復成位圖文件
LONG?GetScale(LFLOAT?ras_xLength,?LONG?rasWidth,?BOOL?isBigFont);?//?計算比例尺
????int?Get_RasterMetadata_by_GridIndex(int?rasrownbr,?int?rascolnbr,?int?*rasIndex);?//?根據格網索引取圖幅
????int?GetImageCLSID(const?WCHAR*?format,?CLSID*?pCLSID);?//?得到格式為format的圖像文件的編碼值,訪問該格式圖像的COM組件的GUID值保存在pCLSID中
????int?Get_PyramidLevel_by_scale(long?userScale,?int?*pyramidLevel);?//?根據比例尺獲取金字塔索引的級別
int?Get_Result_extent(SE_ENVELOPE?*resultExtent);?//?獲取結果位圖的地理范圍
}
;
從CMyRaster類的結構可以看出我將圍繞
RASTER_METADATA *m_RastersMetadata;
這個動態數組來做文章。RASTER_METADATA是一個定義在CMyRaster外面的結構體,細節如下:
typedef?struct?raster_metadata
{
????
//?下面是每個raster對應的唯一屬性
????int????m_RasterID;????//?Raster_ID
????int????m_RasterRowNum;????//?圖幅格網索引行標號
????int????m_RasterColNum;????//?圖幅格網索引列標號
????int????m_QueryTileLeft;?//?查詢范圍對應的tile最左一列的列號????
????int????m_QueryTileRight;?//?查詢范圍對應的tile最右一列的列號????
????int????m_QueryTileTop;?//?查詢范圍對應的tile最上一行的行號????
????int????m_QueryTileBottom;?//?查詢范圍對應的tile最下一行的行號????
????SE_ENVELOPE????m_RasterExtent;?//?全圖的地理坐標范圍????
????IMAGE_EXTENT?m_ImageSize;?//?全圖的像素范圍????
????IMAGE_EXTENT?m_QueryImageSize;?//?與查詢范圍相交的像素范圍????
????IMAGE_EXTENT?*m_QueryTilesSize;?//?查詢范圍對應的每個tile的大小(不帶零)
????
????
//?下面是每個raster中每級金字塔對應的屬性,均為數組,其大小在運行時才能確定????
????IMAGE_EXTENT?*m_ImageSizeByLevel;?//?金字塔該級別上像素范圍????
????IMAGE_EXTENT?*m_ZerosSizeByLevel;?//?金字塔該級別上補零部分的寬與高????
????SE_ENVELOPE????*m_RasterExtentByLevel;?//?金字塔該級別上的地理坐標范圍????
????int????*m_TotalTileColByLevel;?//?金字塔該級別上以tile為單位的列數????
????int????*m_TotalTileRowByLevel;?//?金字塔該級別上以tile為單位的行數
}
RASTER_METADATA;

公有方法GetRaster(…)是完成功能的“主”方法,其中就這么三句話:
//?通過查詢范圍獲取與查詢范圍相交的全部圖幅的元數據
????int?ret?=?Get_RasterMetadata_by_BBox(connection,?ADOConn,?left,?right,?top,?bottom,?scale);
????
if?(ret?!=?SE_SUCCESS)
????????
return?-1;
????
????
//?獲取上面求出的圖幅序列的像素數據
????ret?=?Get_RasterData_from_SDE(connection,?ADOConn);
????
if?(ret?!=?SE_SUCCESS)
????????
return?-1;

????
//?將存儲在臨時文件中的像素數據還原成位圖
????ret?=?Write_to_BMP_file(left,?right,?top,?bottom,?filename);
????
if?(ret?!=?SE_SUCCESS)
????????
return?-1;

邏輯設計中的第一、二步都有與其對應的函數實現。第三至第五步則化為GetRaster(…)中的
//?通過查詢范圍獲取與查詢范圍相交的全部圖幅的元數據
????int?ret?=?Get_RasterMetadata_by_BBox(connection,?ADOConn,?left,?right,?top,?bottom,?scale);
????
if?(ret?!=?SE_SUCCESS)
????????
return?-1;
Get_RasterMetadata_by_BBox函數用于填充m_RastersMetadata數組,以供后面使用。

第六步提取數據由
//?獲取上面求出的圖幅序列的像素數據
????ret?=?Get_RasterData_from_SDE(connection,?ADOConn);
????
if?(ret?!=?SE_SUCCESS)
????????
return?-1;
實現,其依據m_RastersMetadata數組中的數據,通過SDE API提供的讀取圖塊的API來按塊提取數據。取出的數據是以字節流的形式存入磁盤臨時文件,因為公有R、G、B三個波段的數據,所以相應的就有三個臨時文件。

第七步重新繪制圖像則由 //?將存儲在臨時文件中的像素數據還原成位圖
????ret?=?Write_to_BMP_file(left,?right,?top,?bottom,?filename);
????
if?(ret?!=?SE_SUCCESS)
????????
return?-1;

完成,繪制圖像我使用的是GDI+,感覺就是兩個字:簡單,好用。
在這個影像包裝器子系統中,最耗時的環節并不是提取數據和還原圖像,而是連接SDE。也不知是什么原因,當后臺數據庫是Oracle的時候,這個連接動作總是如此如此如~~~此的慢。第一次連接一般要一分鐘左右,以后每次也要幾十秒。如果每次查詢都要連接SDE,那后果簡直不可想象(我曾經做過的一個基于MO的矢量數據發布系統就是每次都要連接,以至于做一次地圖放大或者平移都要等一分多鐘,唉,實在對不起用戶)。所以我把連接SDE的動作放在了InitDialog中,并在整個程序生命期內保持,直到退出時才斷開。
實現方面也就是這樣了。
實測結果,我的影像包裝器響應一次查詢大約要3到6秒,平均不到4秒,不知道一般的指標是多少。我感覺這個速度應該還可以接受吧。
要交代的基本上就是這些了,大家如果看出了我的從設計到實現中什么地方感覺不爽就盡管說,我一定認真聽取,虛心接受,并不斷重構自己的代碼。另外,我不太懂設計模式(那本GoF的書看不下去,不知道還有沒有別的通俗一點的),不知道我做的這個部分從模式的角度看有沒有更好的方案,還請大家指點。
本文方法初級,方案拙劣,代碼不怎么規范,文字也比較晦澀,圖片又比較丑陋,還不會用UML工具展示類圖,浪費各位看官的時間了,罪過罪過。

p.s.項目已經交工幾個月了,我早想借blog總結一下,但苦于博客園是討論.net技術的而一直沒敢post,不過后來幸運天屎從天而降砸到了我的頭上——我發現了WebGIS團隊!這才促使我重新看一遍代碼并總結之,否則好多想法恐怕再過過就隨屎尿而去了……
感謝博客園,感謝WebGIS,感謝CCTV,感謝ChannelV…

轉載于:https://www.cnblogs.com/EggKiller/articles/1079553.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的基于ArcSDE的影像数据管理-解决篇(转载)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲综合p | 黄网站在线播放 | 欧美成人精品欧美一级乱 | 美女黄页网站 | 国产美女一级片 | 蜜桃91麻豆精品一二三区 | 狠狠干欧美 | 男男野外做爰全过程69 | 久久久久久无码精品大片 | 东北老女人av | ts人妖另类精品视频系列 | 亚洲精品欧美在线 | 91免费观看入口 | 色七七久久 | 调教91| 黄色岛国片 | 国产黄色一区二区 | 国产人免费人成免费视频 | 影音先锋激情在线 | 国产精品一级片在线观看 | 免费人妻一区二区三区 | 国产白丝喷水 | 啪啪激情网 | 欧美爱爱免费视频 | 久久精品99国产 | 九一国产在线观看 | 国产女主播喷水视频在线观看 | 草莓巧克力香氛动漫的观看方法 | 国产精品theporn| 黄色99 | 亚洲国产精品久久久久婷婷老年 | 女女h百合无遮涩涩漫画软件 | 性做久久久 | 欧美精品国产动漫 | 4虎tv| 超碰成人福利 | 国产成人精品综合久久久久99 | 超碰人人cao| 久久国产人妻一区二区免色戒电影 | 亚洲女则毛耸耸bbw 边吃奶边添下面好爽 | 亚洲av人无码激艳猛片服务器 | 国产精品高潮呻吟久久av野狼 | 九九九九九伊人 | 一二三av | 一区二区三区视频在线播放 | 久操视频免费观看 | 91一区二区在线观看 | 男生和女生一起差差差视频 | 亚洲综合射 | 99精品久久久久久 | 欧美激情成人在线 | 国产男女猛烈无遮挡免费视频 | 性一交一乱一色一视频麻豆 | 日本免费无人高清 | 国产一二三精品 | 91爱爱影院 | 日韩欧美二区三区 | 丝袜综合网 | 日韩专区在线观看 | 善良的少妇伦理bd中字 | 国产短视频一区 | 永久免费不卡在线观看黄网站 | 97超碰中文字幕 | 黄色av日韩 | 国产99久 | 99热综合 | 91网在线播放 | xx99小雪| 三大队在线观看 | 91蜜桃在线观看 | 国产h视频 | 校园春色欧美 | 我们2018在线观看免费版高清 | 久久美女精品 | 成人伊人 | 青青青国产在线 | 色婷婷久久综合 | 黄色网页观看 | 97视频在线观看免费高清完整版在线观看 | 毛利兰被扒开腿做同人漫画 | 女人高潮娇喘声mp3 乱色视频 | 蜜臀久久99精品久久久画质超高清 | 好屌妞视频这里有精品 | 99久久99| 日本在线网址 | 成人性生活免费看 | 天天舔天天摸 | 136fldh导航福利微拍 | 无码人妻一区二区三区在线 | av中文在线资源 | 欧美成人三级精品 | 天天操,夜夜操 | av手机在线播放 | 一区二区三区国产视频 | 在线观看av毛片 | 黄色性情网站 | 久草婷婷| 欧美极品喷水 | 久久久一区二区三区 |