由不规则离散点集生成TIN与GRIDDEM.docx
《由不规则离散点集生成TIN与GRIDDEM.docx》由会员分享,可在线阅读,更多相关《由不规则离散点集生成TIN与GRIDDEM.docx(21页珍藏版)》请在冰豆网上搜索。
![由不规则离散点集生成TIN与GRIDDEM.docx](https://file1.bdocx.com/fileroot1/2023-2/6/b072e124-962d-45c4-b571-5bcc49c6472b/b072e124-962d-45c4-b571-5bcc49c6472b1.gif)
由不规则离散点集生成TIN与GRIDDEM
由不规则离散点集生成
GRID-DEM
TIN与
由不规则离散点集生成TIN与
GRIDDEM
现阶段生成数字高程模型(DEM)的方法较多,如以摄影测量得到的像对为数据源跟踪生成等高线及DEM,由机载
激光测距仪记录规则点集后生产数据,也可采用传统的地形图扫描后跟踪等高线,记录一连串离散点集,接着运用各类算法进
行处理,最后生成不规则三角网(TIN)与规则格网(GRID)DEM的方法。
本文主要介绍的就是以等高线(参考图一)和
离散点集为数据源,产生TIN与GRIDDEM的技术路线。
具体步骤如下:
1)跟踪等高线生成离散点集,记录在文本文件中。
参考图二和图三。
2)读取文本文件中的数据,进行预处理。
主要工作是找到XY轴方向上最小最大数值,压缩数据范围,避免数据范围跨度太
大或太小,即出现数据分布稠密或稀疏的情况。
while
(!
_demfile.eof())
{
_demfile>>point3dXYZ[i][0]>>point3dXYZ[i][1]>>point3dXYZ[i][2];
point3dXYZ[i][2]=point3dXYZ[i][2]/2;//因为XY轴在随后调整,因此相应调Z
轴数值
if
(xMin>point3dXYZ[
i][0])
xMin=point3dXYZ[
i][0];//得到整个范围的最大与最小数
值
if
(xMaxi][0])
xMax=point3dXYZ[
i][0];
if
(yMin>point3dXYZ[
i][1])
yMin=point3dXYZ[
i][1];
if
(yMaxi][1])
yMax=point3dXYZ[
i][1];
if
(zMin>point3dXYZ[
i][2])
zMin=point3dXYZ[
i][2];
if
(zMaxi][2])
zMax=point3dXYZ[
i][2];
i++;
}
_demfile.close();//文件流读取完毕,关闭
_demfile.clear();//文件流清除
3)完成TIN中点,线,三角形和网的定义。
ClassAFX_EXT_CLASS
TIN_Point
{//TIN中的点
friendclassTIN;
public:
intGet_ID(void){return(m_ID);}//ID数值
constPOINT3d&
GetPoint
(void){return(m_Point);
//
普通的点
double
Get_X(void)
{return
m_Point[0]);
//点上的X数值
double
Get_Y(void)
{return
m_Point[1]);
//点上的丫数值
double
Get_Z(void)
{return
m_Point[2]);
int
Get_Neighbor_Count
(void){return(m_nNeighbors);
//
邻接点的个数
TINPoint
*Get_Neighbor
(int
iNeighborm_Neighbors[iNeighbor]:
NULL);
iNeighbor){return
//得到某一邻接点
iNeighbor>=0&&
int
Get_Triangle_Count
(void){return
TIN_Triangle*
Get_Triangle(intiTriangle)
m_nTriangles?
m_Triangles
[iTriangle]:
NULL);}
private:
TIN_Point(void);
TIN_Point(intID,
POINT3dpptxyz);
m_nTriangles);}
//得到邻接三角形个数
return(iTriangle>=0&&iTriangle<
//构造函数
virtual〜TINPoint
(void);
int
m」D,m_nNeighbors,m_nTriangles;//本身
ID
数值,邻接点个数,邻接三角形个数
POINT3d
m_Point;〃自身存储着XY数值
TINPoint
m_Neighbors;//邻接顶点
TIN_Triangle
m_Triangles
;//邻接三角形
bool
_Add_Neighbor
(TIN_Point*pNeighbor);
//增加
顶点
bool
*pTriangle);
_Add_Triangle
//增加三角形
(TIN_Triangle
bool
DelRelations
(voi
d);
};
ClassAFX_EXT_CLASS
TIN_Edge
//TIN中的边
friendclass
TIN;
//申明友元类
public:
//得到边的
端点
TINPoint*GetPoint
(intiPoint){
return(m_Points[iPoint%2]);
private:
TIN_Edge(TIN_Point*a,TIN_Point
*b);/
/构造函数
virtual〜TIN_Edge(void);
TIN_Point*m_Points[2];
//边的两个端点
I
};
4)以找到预处理后离散点集的最大外包三角形作为队列中第一个三角形开始,依次加入点集中的每个顶点,接着判断此新加
顶点与已经存在的每个三角形的外接圆是否存在包含关系,如果包含,则改变此关联三角形的边信息后,然后以新加入的
顶点和关联三角形的顶点为参数创建新的三角形,最后收尾工作是,以完成的三角化后每个三角形中的顶点为参数,建立
TIN中的顶点、边和三角形之间的关系。
bool
TIN:
:
_Triangulate(TIN_Point**Points,intnPoints,TTIN_Triangle*Triangles,int&nTriangles)
int
i,j,k,inside,
trimax,
double
nedge
emax
status
*complete
xmid,ymid,dma肖
=200,
=0,
=0,
NULL
xp,yp,x1,
y1,x2,y2,x3,y3,xc,yc,r;
TTIN_Edge
*edges
NULL
//TTIN_Edge:
边的结构
〃•
//
//Allocatememoryforthecompletenesslist,flagforeachtriangle
trimax
nPoints;
NULL)
if((
complete
=(int*)malloc(trimax*sizeof(int)))==
//给即将生成的三角形的标志分配内存
status
=1;
if(edges)
free(edges);
//如果不为空,首先释放内存
if(complete)
free(complete);
//■
//Allocatememoryfortheedgelist
if((edges
=(TTIN_Edge*)malloc(emax*sizeof(TTIN_Edge)))==
NULL)
//给边的标志分配内存
status
=2;
if(edges)
free(edges);
if(complete)
free(complete);
并准备不断的添加新顶点
//准备找到最大外包三角形作为三角形队列中第一个三角形
_Extent_Update();
//更新整个离散顶点的矩形范围
dma)=m_Extent.Get_XRange()>m_Extent.Get_YRange()?
m_Extent.Get_XRange():
m_Extent.Get_YRange();
//取范围中XY两轴的较大数值
xmid=
m_Extent.Get_XCenter();
//中心
占
八、、
ymid=
m_Extent.Get_YCenter();
Points
[nPoints
+0]->
m_Point[0]
xmid-20*dmax〃第一个顶点的X数值
Points
[nPoints
+0]->
m_Point[1]
ymid-dmax;//第一个顶点的Y数值,此数值取得相当小
Points
[nPoints
+1]->
m_Point[0]
xmid;
//第二个顶点的X数值
Points
[nPoints
+1]->
m_Point[1]
=ymid+20*dmax//第二个顶点的
Y数值,居中,但偏高
Points
[nPoints
+2]->
m_Point[0]
xmid+20*dmax//第三个顶点的
X数值
Points
[nPoints
+2]->
m_Point[1]
ymid-dmax〃第三个顶点的Y数值,
第三个顶点与第一个顶点高
度相同,在X轴上对称
Triangles[0].p1=nPoints
+0;
//三角形的顶点记录的是顶点数组中的索引
+1;
Triangles[0].p2=nPoints
+2;
Triangles[0].p3=nPoints
complete[0]=false;
nTriangles
=1;
//初始化三角形个数为1
//•
//每次增加一个顶点到已存在的
TIN格网中
for(i=0;i//对于所有顶点进行循环
xp=Points[i]->
m_Point[0];
//使用浮点数进行记录
yp=Points[i]->
m_Point[1];
//使用浮点数进行记录
nedge
始化边的个数为0
=0;
//对于每个顶点,初
//如果顶点位于三角形的外接圆内,则原三角形的三条边被加到一个缓存中,并移走此三角形
//对于所有刚刚建立的三
for(j=0;jvnTriangles;j++)
角形进行循环
if(complete[j])
continue
//此三角形的
完整性不用破坏,继续下次循环
}
判断顶点与外接圆的关系
xp)
此三角形为完整性
if(xc+r<
//顶点落在外接圆之外
{
complete[j]=true;
//标记
x1
=Points[Triangles
[j].
p1]->
m_Point[0];//三角形的三个顶点
y1
=Points[Triangles
[j].
p1]->
m_Point[1];
x2
=Points[Triangles
[j].
p2]->
m_Point[0];
y2
=Points[Triangles
[j].
p2]->
m_Point[1];
x3
=Points[Triangles
[j].
p3]->
m_Point[0];
y3
=Points[Triangles
[j].
p3]->
m_Point[1];
inside
=_CircumCircle(xp,yp,
x1,
y1,x2,y2,x3,y3,&xc,&yc,&);//
}
if(inside)
//顶点落在外接圆里面
{
//检查是否超岀边链表的大小if(nedge+3>=emax)
{
emax+=
100;
sizeof(TTIN_Edge)))==NULL)
//增加边的个数
if((edges=(TTIN_Edge*)realloc(edges,emax*
//增加新的内存分配
{
存储边的信息
引:
1,2;2,3;3,1
}
}
edges[nedge+0].p1
edges[nedge+0].p2
edges[nedge+1].p1
edges[nedge+1].p2
status=3;
if(edges)
if(complete)
=Triangles[j].p1;
=Triangles[j].p2;
=Triangles[j].p2;
=Triangles[j].p3;
free(edges);
free(complete);
//
//顶点的索
edges[nedge+2].pl=Triangles[j].P3;
edges[nedge+2].p2=Triangles[j].pi;
个数加上
来
形的循环
edges[k].
-1;
edges[k].
nedge+=3;//对于最外层循环的顶点来说,相关边的
3
Triangles[j]=Triangles[nTriangles-1];/将链表中最后一个二角形赋值过
complete[j]=complete[nTriangles-1];
nTriangles--;
//三角形个数减去
j--;
}
//对应:
if(inside)
}//结束对所有三角
//标记被重复使用的边
//若三角形以逆时针方向存储,则内部被多次使用的边存储的顶点顺序是相反的
for(j=0;j{
for(k=j+1;k{
if((edges[j].p1==edges[k].p2)&&(edges[j].p2==
p1))//同样的一条边存储的方向刚刚相反
{
edges[j].p1=
//做标记
edges[j].p2=-1;
edges[k].p1=-1;
edges[k].p2=-1;
}
if((edges[j].p1==edges[k].p1)&&(edges[j].p2==
p2))//同样的一条边
{
edges[j].p1=-1;
edges[j].p2=-1;
edges[k].p1=-1;
edges[k].p2=-1;
}
//组成新三角形
//忽略所有已经打过标志的边
//所有的边以顺时针方向安排
for(j=0;jvnedge;j++)
{
if(edges[j].pl<0||edges[j].p2<0)//比如等于
-1的情况
{
continue;
}
if(nTriangles>=trimax
{
status=4;
if(edges)if(complete)
}
Triangles[nTriangles].p1
引
Triangles[nTriangles].p2
Triangles[nTriangles].p3
索引
complete[nTriangles]
nTriangles++;
}
}
for(i=0;i<;i++)
free(edges);
free(complete);
=edges[j].p1;//记录关联的边的一个顶点索
=edges[j].p2;//记记录关联的边的另一个顶点索引
=i;//对于最外层循环的顶点来说,记录此顶点的
=false;
//对所有的顶点循环完毕//对应着
//
//移走初始定义的大外接三角形
//这些三角
//Removetriangleswithsupertriangle
vertices
//ThesearetriangleswhichhaveavertexnumbergreaterthannPoints
形的顶点索引超岀了顶点个数
for(i=0;iif(Triangles[i].p1>=nPoints
||Triangles[i].p2>=nPoints
||Triangles[i].p3>=nPoints)
{
Triangles[i]=Triangles[nTriangles-1];//不断的把最后一个三角形赋值
过来
nTriangles--;
i--;
}
}
return(status==0);
}
5)对TIN中的三角形进行循环,以每个三角形的顶点为参数,插值生成GRIDDEM。
参见图四.
图一:
等高线图
洒因⑷5^00576QC^57BQWJ
IIiIIII
I*
|k
;、」=-■11,i■_
tw广J」二'二7
厂二
Y/iJii、_厂■—厂"Jd.、
i/JffFTL
f
d•-J上三二
7
TI「rq:
G
Si±J?
A
J/:
广
ICO:
20003COO4000MOH60507000RO32-MOO10:
00110001?
00flU00C-1£OlO1S-30017COO1B00C
图二:
离散点
57E(JC^
10fl:
2OCD3?
0OJOOO500?
SCIO7D0:
创畀MCO10:
00MOO,]IPOOC13-SiO*」SOOO1G3Mt7C?
09XK
blCOH馬
g
nRB5.DiK良3曲.
QHIMNCE-003:
1口冃二丿>|口_!
|_.||「口=呂名呂2〔34—g邛HI总COZ8MG■,"i"IHM~i~Ilil「~t~!
「zJIf"•「i~
图三:
导出的数据存储在文本中
QfJ.;ZJ-i■毋社fhUUVUUU
S75870.000000575951-335765575750.000000575730,0^eiS€575763.92536EE757S5.000300£-?
5^34^5445«575£73pQ00300575SSS哎575950・QQgg576003・2哙3吐二工576016,3勺呂57597^■厉52五石;35fi2OlO>OOO0OO562032.7^2230562010.000000562001.65£826562010-000000562010.000000577760.000000577850.000000577949.000000577753.000000577724.Q-71B67577670.ODOODCi577S80.000000
5^1^312.120915
571^324.SS82575717345.2760€3571^414.358:
5^571-7SC4.A8S2S75717321.179-389
.555*5-
5717^^3■书呂220©5717^34・电电225丁57177€5.巧召甫E815717774■右W325757173€4■廿巧已2575717^54.8£825^571^824・2239自2571«S74.335x57571^^13.^23731571^074■為E325T571^824.228952571^3^4.^23952571^552.209445571€811■唱疔23五石571^515.50770557K852.209445571SS74.8^8257571€3^S・3吗1329
5716909.0^4165
图四:
生成的GRIDDEM
>囚七.茫审冋翌XI,
昭g£总妃昌DEMg
47.000000
47.000000
47.000000
^37.000000
^7.000000
47.000000ma越g
^7.000090i7..00Q090EQQQ00Q攻7・00000017.000090^7..DQOOQO£吕・00000048.000000今E・000000处.000000^8.0000004?
.00000050,00000050・0QOODO50.00000051.00000051,00000051・000000
51.000000