王光昇,付海龍,周麗珠(天津市測繪院,天津 300381)
二三維平臺間管線數據同步編輯的實現
王光昇?,付海龍,周麗珠
(天津市測繪院,天津 300381)
摘 要:目前,正在開展的全國城市地下管線普查對于管線數據質量提出了更高要求,一般的管線數據檢查都只針對二維數據。如果在二維數據檢查和編輯的過程中能夠實時顯示三維模型,對作業人員而言,就能夠非常直觀、快速地發現比較明顯的空間關系錯誤,對提高管線數據質量具有重要的意義。本文提出了在二三維平臺間實現管線數據同步編輯的方法。
關鍵詞:地下管線;三維;同步;管線普查
城市地下管線是保障城市運行的重要基礎設施,是城市的“生命線”。為了對城市地下管線信息進行科學管理和有效利用,為城市規劃、建設和管理提供準確的管線數據,全國各省市開展了地下管線普查工作。管線普查所生產的數據量非常大,數據質量的優劣直接關系著地下管線管理的正確性和有效性。一般對于管線數據的檢查都只是針對二維數據的基本屬性、邏輯關系等的檢查,而很少考慮三維空間關系的正確性。
我院對管線數據的采集是基于AutoCAD環境二次開發的軟件,同時,在GIS市場運營過程中也開發了基于OSG(Open Scene Graph)的三維管線平臺。但是,數據的采集與三維展示二者是分離的,作業員只處理二維數據,不考慮三維空間關系中是否正確,而三維平臺僅僅是作為數據展示的工具,并沒有考慮作業人員的實際應用,當發現錯誤的以后,需要將數據返回給作業員去修改,拖長了數據生產周期。如果作業人員在編輯和檢查二維數據的同時能夠實時地看到三維結果,那么就可以方便、快速發現問題,在數據的源頭避免出現更多問題,這樣就可以大大縮短數據檢查修改的周期。本文采用命名管道、DotSpatial、反應器等技術實現了管線數據在二三維平臺間的同步編輯。
國內已經實現的二三維同步操作的平臺一般都是在基于同一個進程的專用管理平臺,與數據生產人員的聯系不夠緊密。而本文研究的是兩個進程間的同步編輯操作,即AutoCAD軟件與自主研發三維平臺間的通信,它為管線數據生產人員提供了一種實時查看三維模型的技術手段。
2.1命名管道
命名管道(Named Pipes)是一種簡單的進程間通信(IPC)機制,支持可靠的、單向或雙向的數據通信。不同于匿名管道,命名管道可以在不相關的進程和不同計算機之間使用,服務器建立命名管道時給它指定一個名字,任何進程都可以通過該名字打開管道的另一端,根據給定的權限和服務器進程通信。
在WCF(Windows Communication Foundation)中,使用NetNamedPipeBinding類實現了Windows的命名管道機制。但是限定了在使用命名管道的服務時只能接收來自同一臺機器的調用,因此必須指定明確的本機器名或直接寫localhost,并且每臺機器只能打開一個命名管道。
本文中,我們選擇WCF中的命名管道機制實現在同一臺機器上建立三維應用程序與AutoCAD平臺之間的通信,使得管線作業人員在數據生產編輯、檢查的同時,能夠實時地看到三維效果。
2.2DotSpatial
DotSpatial是一個基于.NET 4.0,使用C#語言開發的開源地理信息系統類庫,該類庫集成了地圖顯示、編輯、查詢、空間分析等常用的GIS功能,是目前比較成熟的開源GIS類庫。
本文在實現二三維管線數據同步編輯的過程中, 以shpefile格式的數據作為中間數據,作業人員在AutoCAD中編輯二維數據時,通過自定義反應器處理函數,調用DotSpatial組件同步修改shapefile數據,最后將修改的結果在三維平臺中實時顯示。
2.3反應器
反應器是AutoCAD中的一種反饋機制,它類似于Windows的消息處理,可以響應輸入事件、實體編輯等事件。AutoCAD中的反應器主要包括數據庫反應器、對象反應器、編輯器反應器等。
實現管線數據從二維到三維同步編輯的基本流程如圖1所示。

圖1 從二維到三維的同步流程
通過WCF的命名管道技術實現AutoCAD平臺與三維平臺的同步操作,首先要創建服務器端和客戶端,建立起進程間的通信??紤]到程序功能的獨立性和調試的方便,我們將服務器端宿主在一個獨立的.NET應用程序中,而將AutoCAD和三維平臺都作為客戶端??蛻舳伺c服務器之間的通信是雙向的,上述流程僅演示了從AutoCAD客戶端發消息給服務器,然后由服務器處理消息后再提交給三維平臺客戶端的過程。
3.1WCF服務模型
WCF是面向服務的應用程序框架,與WCF服務的所有通信都是通過該服務的終結點進行的。終結點包含4個屬性:地址(Address)、綁定(Binding)、契約(Contract)和行為(Behavior)。
地址:包含服務的位置和傳輸協議,唯一地標識終結點。
綁定:指定如何與終結點進行通信,封裝了傳輸協議、消息編碼、通信模式、可靠性、安全性、事務傳播以及互操作性等特征。
契約:是WCF的消息標準,是服務的提供者和服務消費者進行交互的手段,它告訴客戶端如何與服務器聯系。
行為:客戶端的行為體現的是WCF如何進行服務調用的方式,而服務端的行為則體現了WCF的請求分發方式。
3.2服務器端的實現過程(1)定義和實現服務契約。定義:
[ServiceContract(SessionMode=SessionMode.Allowed)]
public interface IFromClientToServerMessages
{
[OperationContract(IsOneWay=true)]
void Register(Guid clientID,string clientName);
[OperationContract(IsOneWay=true)]
void DisplayTextOnServerAsFromThisClient(Guid clientID,string text);
}
實現:
public void Register(Guid clientID,string clientName) {
if (! _registeredClients.Keys.Contains(clientID)) {
_registeredClients.Add(clientID,clientName);
}
}
public void DisplayTextOnServerAsFromThisClient(Guid clientID,string text) {
/ /處理來自客戶端發送過來的信息}
(2)在宿主進程中,為服務構建ServiceHost的實例,并暴露終結點信息。
可以看出,契約接口IFromClientToServerMessages定義的兩個函數是客戶端向服務器發出的請求,需要在服務器宿主應用程序中來處理客戶端的請求,也就是要在服務器端來實現這兩個函數。其中,Register函數是客戶端連接服務器時發出的請求注冊,參數clientName用來區分客戶端是AutoCAD或三維平臺;函數Display-TextOnServerAsFromThisClient是客戶端發送給服務器的文本信息處理函數。我們需要在宿主應用程序類中繼承IFromClientToServerMessages接口,如下:
public partial class Form1 : Form,IFromClientToServerMessages
{
ServiceHost _serverHost;
Dictionary<Guid,string>_registeredClients=new Dictionary<Guid,string>();
NetNamedPipeBinding _bind=new NetNamedPipeBinding ();public Form1() {
InitializeComponent();
_serverHost=new ServiceHost(this);
_bind.MaxBufferPoolSize=2147483647;
_bind.MaxBufferSize=2147483647;
_bind.MaxReceivedMessageSize=2147483647;
_serverHost.AddServiceEndpoint((typeof(IFrom-ClientToServerMessages)), _ bind," net.pipe:/ / localhost/ Acad-Server");
_serverHost.Open();
} / /...}
ServiceHost對象負責管理服務的生存周期,通過AddServiceEndpoint方法將服務終結點添加到承載服務中,該方法接收的參數分別是契約(Contract)、綁定(Binding)和地址(Address)。
(3)打開通訊通道提供服務
客戶端與服務之間的通信是雙向的,它們通過彼此的地址(Address)標識就可以隨時訪問對方。這里需要用到通道工廠(ChannelFactory),它接收服務協定接口作為泛型參數,這樣創建出來的實例稱為該協定的通道工廠。顧名思義,這個工廠專門用于生產通道,這個通道就是架設在服務器終結點和客戶端終結點之間的通信通道了。由于這個通道是用服務協定來創建的,所以就可以在這個通道上調用這個服務協定的操作了。例如,從服務器向客戶端發送信息的方法如下:
private void SendText(Guid client,string text) {
using (ChannelFactory<IFromServerToClientMessages>factory = new ChannelFactory<IFromServerToClientMessages>(_bind, new EndpointAddress(" net.pipe:/ / localhost/
AcadClient_" + client.ToString()))) { IFromServerToClientMessages serverToClientChannel =factory.CreateChannel();serverToClientChannel.DisplayTextInClient(text);
} / / using
}
該實現過程可以簡單地描述成:在服務器端打開客戶端通道,向客戶端發送消息。
3.3客戶端的實現過程
(1)定義和實現的服務契約:
[ServiceContract(SessionMode=SessionMode.Allowed)]
public interface IFromServerToClientMessages
{
[OperationContract(IsOneWay=true)]
void DisplayTextInClient(string text);/ /處理來自服務器端發送過來的信息
}
(2)其他的實現過程和服務器端的實現類似,其中,向服務器發送信息的實現方法為:
public void SendTextToServer(string text) {
using (ChannelFactory<IFromClientToServerMessages>factory=new
ChannelFactory<IFromClientToServerMessages>(_bind, new
EndpointAddress ( " net.pipe:/ / localhost/ AcadServer")))
{ IFromClientToServerMessages clientToServerChannel =factory.CreateChannel();clientToServerChannel.DisplayTextOnServerAs-FromThisClient(_clientID,text);
}
}
同樣,SendTextToServer函數可以簡單地描述成:在客戶端打開服務器端通道,向服務器端發送消息。
3.4AutoCAD客戶端的消息監控
作業人員應用AutoCAD進行管線數據的編輯過程中,產生了數據編輯、窗口縮放、鼠標移動等事件,這些事件是二三維同步的源頭,我們首先要在AutoCAD中捕獲這些事件。
(1)對象編輯事件
通過對象編輯反應器來捕獲數據新增、修改信息,將變化后對象的位置和點號等屬性信息發送給服務器,然后由服務器通知DotSpatial去更新相應的shp數據。反應器的添加如下:
Document doc = acApp.DocumentManager.MdiActiveDocument;
doc.Database.ObjectModified += Database_ObjectModified;
(2)視圖變化事件
在AutoCAD中,影響視圖變化的因素主要有兩種:一種是鼠標拖動、鼠標滾輪等窗口消息。另一種是操作圖形窗口的AutoCAD命令,如ZOOM、PAN、RTZOOM、RTPAN等。AutoCAD中視圖發生變化后,我們必須及時地將當前視圖范圍信息發送給服務器,由服務器通知三維平臺更新視圖范圍,這樣才能產生較好的同步效果。
對于窗口消息,通過PreTranslateMessage消息預處理響應函數來捕獲,方法為:
public static Delegate pHandler;
pHandler = new PreTranslateMessageEventHandler ( messageEv);
public void messageEv ( object sender, PreTranslateMessag-eEventArgs e) {
Document mdiActiveDocument=acApp.DocumentManager.MdiActiveDocument;
if (mdiActiveDocument = = actdoc) { if (e.Message.message = = 0xc1f0 | | e.Message.message = = 520 | | e.Message.message = = 0x20a | | e.Message.message = = 0x20e) {
Editor editor = acApp.DocumentManager.Mdi-ActiveDocument.Editor;ExecuteInApplicationContextCallback callback =new ExecuteInApplicationContextCallback(_Lambda);acApp.DocumentManager.ExecuteInApplicationContext(callback,null);
}
} / / if
}
對于AutoCAD命令,通過命令反應器來捕獲,方法為:
public static Delegate eHandler;
eHandler=new CommandEventHandler(cmdEnded);
public void cmdEnded(object o,CommandEventArgs e) { string globalCommandName=e.GlobalCommandName;string[] cmds = new string[9]{" -PAN"," ZOOM"," PAN","RTZOOM","RTPAN", " VIEW"," REGEN"," REGENALL"," REDRAW"};
if (cmds.Contains(globalCommandName))
{ Editor editor=acApp.DocumentManager.MdiActive-Document.Editor;ExecuteInApplicationContextCallback callback=new ExecuteInApplicationContextCallback(_Lambda);
acApp.DocumentManager.ExecuteInApplication-Context(callback,null);
}
}
其中,_Lambda函數實現了獲取AutoCAD當前視圖的范圍,然后通過命名管道技術將視圖范圍發送給服務器,再由服務器更新三維平臺的視圖范圍。
[CompilerGenerated,DebuggerStepThrough]
private void _Lambda(object a0)
{
Document doc = acApp.DocumentManager.MdiActive-Document;
Editor ed=doc.Editor;
Matrix3d ucs=ed.CurrentUserCoordinateSystem;
Point3d vc = ((Point3d) acApp.GetSystemVariable( " VIEWCTR")).TransformBy(ucs);
Vector3d vd=new Vector3d(0,0,1);
double vpHeight = ((double) acApp.GetSystemVariable ("VIEWSIZE"));
Point2d screensize=(Point2d)acApp.GetSystemVariable ("Screensize");
double vpWidth=vpHeight?screensize.X / screensize.Y;
Point2d centerPoint=new Point2d(vc.X,vc.Y);Vector3d viewDirection=vd;
double x0=centerPoint.X - vpWidth / 2.0;double y0=centerPoint.Y - vpHeight / 2.0;double x1=centerPoint.X + vpWidth / 2.0;double y1=centerPoint.Y + vpHeight / 2.0;/ /調用SendTextToServer函數,向服務器發送信息}
3.5DotSpatial更新shp數據
這里以管線為例說明用DotSpatial更新shp數據的步驟:
由AutoCAD的反應器傳遞過來的管線編輯信息中,包含了管線的坐標以及起始點號、終止點號、管徑等所有屬性信息。
(1)首先根據管線亞類信息,打開相應的管線文件。
IFeatureSet fs=FeatureSet.Open(strVectorFile);
(2)根據管線的坐標范圍選擇管線。
Extent ext=new Extent(minx,miny,maxx,maxy);
List<int>ids=fs.SelectIndices(ext);
(3)遍歷選擇的所有管線,通過比較起始點號、終止點號找到目標管線,然后編輯坐標、修改屬性。
IFeature feat=fs.GetFeature(id);/ /比較點號
feat.DataRow.BeginEdit();
List<Coordinate>points=new List<Coordinate>();points.Add(new Coordinate(x0,y0));points.Add(new Coordinate(x1,y1));feat.Coordinates=points;feat.DataRow.EndEdit();/ /修改屬性…
(4)保存文件。
fs.SaveAs(strVectorFile,true);
3.6三維渲染
三維平臺采用OSG開發,在本文所述的同步流程中,作為一個客戶端接收來自服務器的指令。當二維數據更新之后,shp數據也隨之更新了,三維平臺會按照服務器的指令重新將shp數據渲染成三維模型。對于三維平臺的實現方法本文不作具體論述。
3.7成果展示
二三維進程間的同步如圖2所示。
在控制面板中,選擇“啟動服務”后,就啟動了Au-toCAD和三維應用程序間通信的服務器;選擇“同步”選項后,在AutoCAD窗口中的任何與視圖相關的操作,如縮放、平移、全屏等,在三維窗口中都會實時改變視圖,與二維窗口保持一致。
對于數據檢查的錯誤,我們將二維數據的錯誤發送到AutoCAD的錯誤定位窗口中,對于發生碰撞的三維空間錯誤發送到三維窗口中。三維窗口中的紅色箭頭指示了碰撞的位置,如圖2所示。

圖2 二三維同步
本文論述了如何采用基于WCF的命名管道技術實現AutoCAD平臺與三維平臺間進程間的通信,在此基礎上,結合反應器、視圖同步、DotSpatial空間處理組件等技術實現管線數據在二三維平臺間的同步編輯。該方法可以幫助作業人員快速地發現管線三維空間的問題,提高管線數據質量。
參考文獻
[1] 蔣金楠.WCF全面解析(上冊)[M].北京:電子工業出版社,2012:294~343.
[2] 嚴商.基于WCF的分布式程序的研究與實現[D].武漢理工大學,2008:18~24.
[3] 吳清壽.基于WCF的分布式系統模型研究與實現[J].吉林師范大學學報·自然科學版,2012,8(3):61~64.
[4] 胡玉貴.基于WCF的雙工操作研究[J].現代計算機(專業版),2008(08):74~76.
[5] Justin Smith.WCF技術內幕[M].武漢:華中科技大學出版社,2010:181~195.
[6] Autodesk.ObjectARX開發指南.1999.
[7] 肖鵬,劉更代,徐明亮.OpenSceneGraph三維渲染引擎編程指南[M].北京:清華大學出版社,2010.
[8] 王銳,錢學雷.OpenSceneGraph三維渲染引擎設計與實踐[M].北京:清華大學出版社,2009.
Realization of Synchronous Editing of Pipeline Data Between Two and Three Dimensional Platform
Wang Guangsheng,Fu Hailong,Zhou Lizhu
(Tianjin Institute of Surveying and Mapping,Tianjin 300381,China)
Abstract:At present,the ongoing national urban underground pipeline survey is carried out,and put forward higher requirements for the pipeline data quality,the general pipeline data are only for two-dimensional data.If in the process of 2D data checking and editing,we can display 3D model in real time,to the operator,can very intuitive,quickly found more obvious spatial relationship errors,and to improve the data quality of the pipeline has important significance.In this paper,the method of realizing the synchronous editing of pipeline data between two and three dimensional platforms is presented.
Key words:underground pipeline;3D;synchronization;pipeline survey
文章編號:1672-8262(2015)05-75-05中圖分類號:P208.1
文獻標識碼:B
收稿日期:?2015—05—10
作者簡介:王光昇(1979—),男,高級工程師,主要從事基礎地理信息數據處理工作。