馬鵬剛,王永紅,周群強(qiáng),趙寶軍,張鵬巖
(1.國(guó)家測(cè)繪地理信息局第二地形測(cè)量隊(duì),陜西 西安 710054;2.河南大學(xué) 環(huán)境與規(guī)劃學(xué)院,河南 開(kāi)封 475004)
數(shù)字地形圖是“數(shù)字城市”、“數(shù)字地球”的重要組成部分,在城市建設(shè)和規(guī)劃中起著重要作用。在大比例尺地形圖(1∶500、1∶1 000、1∶2 000)中,特定地物、建筑物、停車(chē)位、院落等均為重要要素,其屬性的準(zhǔn)確性直接影響用戶的使用情況。航空攝影測(cè)量時(shí),由于地形條件、投影變換、采集誤差等因素,使得本來(lái)為矩形的地物要素變?yōu)橐话愕乃倪呅?,?dǎo)致地圖失真,為了能準(zhǔn)確反映地物要素的實(shí)際情況,需要將四邊形修正為矩形。然而,單純?nèi)斯ば拚男屎蜏?zhǔn)確度都很低,因此本文采用條件極值法,以北京地區(qū)停車(chē)位信息采集為例,利用GIS的二次開(kāi)發(fā)技術(shù)編寫(xiě)了自動(dòng)直角化軟件。首先提取四邊形的中點(diǎn),以平行于長(zhǎng)邊的平行線為中線;再將四邊形旋轉(zhuǎn),相鄰兩邊互相垂直,中點(diǎn)不變,使其保持原來(lái)的中心位置。
一般情況下,野外測(cè)量或內(nèi)業(yè)采集時(shí)得到的圖形為矩形,但在進(jìn)行預(yù)處理時(shí),由于測(cè)量誤差、投影轉(zhuǎn)換、加密控制等因素,將導(dǎo)致矢量圖形發(fā)生變形,甚至位移,使得矩形變成平行四邊形[1-3],如圖1所示。
圖1 四邊形產(chǎn)生的原因與表現(xiàn)形式
偽矩形的存在,使得地圖表達(dá)與實(shí)際情況存在差異,直角化時(shí)必須保證中點(diǎn)位置不變。目前運(yùn)用最多的方法是最小二乘法[4],其具有技術(shù)優(yōu)化、方便快捷的優(yōu)點(diǎn),但只是將平行四邊形簡(jiǎn)單直角化,車(chē)位位置卻發(fā)生了偏移,不能滿足采集北京地區(qū)停車(chē)位的位置和面積信息的要求。經(jīng)過(guò)反復(fù)試驗(yàn),將條件極值法與最小二乘法相結(jié)合,利用GIS的二次開(kāi)發(fā)功能,以編程的形式開(kāi)發(fā)了直角化軟件。該方法確保了圖形中點(diǎn)固定不變,長(zhǎng)邊中點(diǎn)以一定的角度旋轉(zhuǎn),直至四邊相互垂直。
在約束條件下,函數(shù)z=f(x1, x2, x3, …, xn)的陣列數(shù)為[4-5]:
令 F(x1, x2, x3, …, xn)=f(x1, x2, x3, ..., xm)+∑∮iβi(x1,x2, x3,…, xn)k∈n, ∮i∈m,分別對(duì) x1, x2, x3, …, xn求偏導(dǎo)數(shù)。要使得函數(shù)z=f(x1, x2, x3,…, xn)存在極值,則其對(duì)各變量的偏導(dǎo)數(shù)為零。根據(jù)原始陣列和偏導(dǎo)數(shù)方程可求出z=f(x1, x2, x3, …, xn)極值時(shí)的x1, x2, x3, …, xn和∮1,∮2, …,∮m。
進(jìn)行四邊形直角化時(shí),要確保其幾何中心不變,反將其中線圍繞中點(diǎn)進(jìn)行旋轉(zhuǎn)。這種算法類似一種近似值,即直角化后矩形的四角無(wú)限接近于90°,但不為90°,如圖2a所示。首先,將原來(lái)的四邊形(紅色邊線)沿長(zhǎng)軸以A方向旋轉(zhuǎn)[5-7],使得長(zhǎng)軸的方位角無(wú)限接近于零,則四邊形的四角將無(wú)限接近于90°,由于條件極值的數(shù)學(xué)模型為陣列式,因此其永遠(yuǎn)不能到達(dá)設(shè)定值,即紅色長(zhǎng)軸與藍(lán)色長(zhǎng)軸近似重疊,但不重疊;然后,將紅色長(zhǎng)軸沿B方向旋轉(zhuǎn)至藍(lán)色長(zhǎng)軸,使得長(zhǎng)軸的方位角無(wú)限接近于零,則四邊形的四角將無(wú)限接近于90°,由于條件極值的數(shù)學(xué)模型為陣列式,因此其永遠(yuǎn)不能到達(dá)設(shè)定值,即紅色長(zhǎng)軸與藍(lán)色長(zhǎng)軸近似重疊,但不重疊。兩種方向所得結(jié)果一致,但旋轉(zhuǎn)半徑不同,因此利用數(shù)學(xué)基礎(chǔ),將A方向(即最短距離方向)設(shè)定為旋轉(zhuǎn)長(zhǎng)軸。
圖2 旋轉(zhuǎn)順序與成果
對(duì)四邊形(紅色)進(jìn)行直角化后,其相鄰兩邊相互垂直,則直角對(duì)應(yīng)的限制條件為:
當(dāng)四邊形存在非直角以及兩個(gè)長(zhǎng)軸沒(méi)有重合時(shí),進(jìn)行旋轉(zhuǎn)處理,將式(1)進(jìn)行線性化處理可得到四角直角化后的參數(shù)。
GIS的二次開(kāi)發(fā)是面向?qū)ο蟮某绦蛟O(shè)計(jì)(OPP),本文以前期作業(yè)區(qū)北京地區(qū)停車(chē)位信息采集矢量數(shù)據(jù)(.mdb)為例,基于GIS的ArcObject,以Microsoft Visual Studio 2010為開(kāi)發(fā)環(huán)境,以Visual Basic為開(kāi)發(fā)語(yǔ)言進(jìn)行程序開(kāi)發(fā)。對(duì)象(Object)為停車(chē)位,類(Class)為四邊形,繼承(Inher)為可不旋轉(zhuǎn)圖形。
圖3 四邊形直角化實(shí)現(xiàn)過(guò)程
1)將四邊形的坐標(biāo)按順時(shí)針?lè)较蚺判?,以中點(diǎn)為基點(diǎn),四角分別為A、B、C、D,如圖3所示。
2)為了避免單純旋轉(zhuǎn)得到如圖2b所示的結(jié)果,即只進(jìn)行旋轉(zhuǎn),而未進(jìn)行垂直處理,需計(jì)算a角的度數(shù),并將其與90°作減法,再按照得出的角度進(jìn)行有目的的旋轉(zhuǎn),代碼為:
//Console.WriteLine("Stand:{0},L1:{1},L2:{2},L3:{3},L4:{4},LS-L1:{5},LS-L2:{6},LS-L3:{7},LS-L4:{8}", lStand.Angle, l1.Angle, l2.Angle, l3.Angle, l4.Angle,
//lStand.Angle-l1.Angle, lStand.Angle-l2.Angle,lStand.Angle-l3.Angle, lStand.Angle-l4.Angle);
double AngleDiff1= Math.Abs(lStand.Angle-l1.Angle);
double AngleDiff2= Math.Abs(lStand.Angle-l2.Angle);
double AngleDiff3= Math.Abs(lStand.Angle-l3.Angle);
double AngleDiff4= Math.Abs(lStand.Angle-l4.Angle);
double ad1= Math.Min(AngleDiff1, AngleDiff3);
double ad2= Math.Min(AngleDiff2, AngleDiff4);
‘和軸線平行
double ParallelLineLength= 0;
‘和軸線垂直
double VerticalLine= 0;
if (ad1 < ad2)//1-2 或 3-4
{
ParallelLineLength= (l1.Length + l3.Length) / 2;
VerticalLine= (l2.Length + l4.Length) / 2;
else//2-3或4-1
{ParallelLineLength= (l2.Length + l4.Length) / 2;
VerticalLine= (l1.Length + l3.Length) / 2;}
double Angle= lStand.Angle;
double HalfPi= Math.PI / 2;
PointClass cp= new PointClass();
‘沿軸線前進(jìn)一半
cp.ConstructAngleDistance(pi.Centroid, Angle,ParallelLineLength / 2);
PointClass cp1= new PointClass();
PointClass cp2= new PointClass();
PointClass cp3= new PointClass();
PointClass cp4= new PointClass();
Angle += HalfPi;
cp1.ConstructAngleDistance(cp, Angle, VerticalLine / 2);
Angle += HalfPi;
cp2.ConstructAngleDistance(cp1, Angle, ParallelLineLength);
Angle += HalfPi;
cp3.ConstructAngleDistance(cp2, Angle, VerticalLine);
Angle += HalfPi;
cp4.ConstructAngleDistance(cp3, Angle, ParallelLineLength);
/Console.WriteLine("({0},{1})({2},{3})({4},{5})({6},{7})", cp1.X,cp1.Y,cp2.X,cp2.Y,cp3.X,cp3.Y,cp4.X,cp4.Y);
‘找到每組中心點(diǎn)距離最大的兩個(gè)點(diǎn)連成直線
‘考慮只有一個(gè)圖形的極端情況
List<ParallelogramInfo> lstGroupParallelogramInfo=new List<ParallelogramInfo>();
List<int> lstOID= new List<int>();
do
{
‘由于存在跳躍,每次都全部遍歷
for (int i= 0; i < lstParallelogramInfo.Count; i++)
{
ParallelogramInfo pi= lstParallelogramInfo[i];
if (lstOID.Contains(pi.OID))
continue;
Console.WriteLine(string.Format("{0}/{1}", lstOID.Count, lstParallelogramInfo.Count));
‘只有一個(gè)的情況
if (lstGroupParallelogramInfo.Count== 1)
‘找到每組中心點(diǎn)距離最大的兩個(gè)點(diǎn)連成直線
‘考慮只有一個(gè)圖形的極端情況
// List<ParallelogramInfo> lstGroupParallelogramInfo= new List<ParallelogramInfo>();
// List<int> lstOID= new List<int>();
‘由于存在跳躍,每次都全部遍歷
/ for (int i= 0; i < lstParallelogramInfo.Count; i++)
3)將原始四邊形的中點(diǎn)與旋轉(zhuǎn)后的四邊形(此時(shí)由于還未作垂直處理,不能稱其為矩形)定位重合。
4)已計(jì)算得到a角的值,根據(jù)角度值作垂直處理,并設(shè)計(jì)界面,代碼為:
<Window x:Class="Revise2Rect.FrmMain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="圖形校正" Height="800" Width="800" Wi ndowStartupLocation="CenterScreen" Icon="default.ico"Closing="Window_Closing">
<Window.Background>
<LinearGradientBrush EndPoint="1,1"StartPoint="0,0">
<GradientStop Color="LightBlue" Offset="0" />
<GradientStop Color="LightGreen" Offset="0.5" />
<GradientStop Color="#FFBE5A5A" Offset="1" />
</LinearGradientBrush>
</Window.Background>
輸出結(jié)果如圖4所示。
圖4 輸出結(jié)果
實(shí)驗(yàn)證明,本文所提出的方法對(duì)于四邊形(多邊形還未實(shí)現(xiàn))進(jìn)行直角化的效果明顯,最終成果已無(wú)限接近矩形,避免了部分軟件直角化時(shí)產(chǎn)生的四邊形失真或中心位移問(wèn)題。對(duì)于四邊形四邊較小的圖形,其邊長(zhǎng)直接影響直角化效果,四邊越接近,直角化效果越明顯。本文設(shè)定的條件極值模型能快速、簡(jiǎn)單、精準(zhǔn)地進(jìn)行直角化處理,但目前還不適用于其他多邊形的直角化。四邊形以上的多邊形直角化算法相對(duì)復(fù)雜一些,后續(xù)可根據(jù)項(xiàng)目要求繼續(xù)探討。