空间数据拓扑关系的自动生成
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
double dy1=first->end->y-first->head->y;
double dy2=second->end-ቤተ መጻሕፍቲ ባይዱy-second->head->y;
double cx=second->head->x-first->head->x;
double cy=second->head->y-first->head->y;
由于GIS的数据量大,造成了判断的工作量大,效率低下的弊端,在判断两条弧段的关系时,应尽可能的减少计算量,减少计算量的工作可以分两步来做,首先是判断两条弧段的最小矩形壁包(Minimum bouding rectangle,MBR)是否相交或具有包含关系,如果不相交或没有包含关系,那么可以断定两条弧段是不互相交的,如果相交或具有包含关系,则进一步判断第一条弧段的每一条组成线段是否和第二条弧段的MBR相交或被包含,如果不相交或没有被包含则可以判断这一部分线段不会和第二条弧段相交,否则可以使用这一条线段与组成第二条弧段的各个线段进行相交关系的判定来确定交点。
拓扑关系自动生成算法的一般过程为:
1.弧段处理,使整幅图形中的所有弧段,除在端点处相交外,没有其他交点,即没有相交或自相交的弧段。
2.结点匹配,建立结点、弧段关系。
3.建立多边形,以左转算法或右转算法跟踪,生成多边形,建立多边形与弧段的拓扑关系。
4.建立多边形与多边形的拓扑关系。
5.调整弧段的左右多边形标识号。
List<Arc*> Arcs;//弧段集合
List<Arc*> NewArcs;//处理后的弧段集合
void BreakArc(Arc *arc)
{
Arc * first=0;//打断后的第一部分
Arc * second=0;//打断后的第一部分
bool IsSelfCross=false;
int LineCountofArc=弧段所包含的直线段数目;
for(int i=0;i<LineCountofArc-2;i++)
{
for(int j=i+2;j<LineCountofArc;j++)
{
if(直线段i和直线段j相交)
{
将交点P插如弧段,并在P处将弧段断为两截,分别存入first和second
中;
IsSelfCross=true;
Break;
double temp=dx1*dy2-dy1*dx2;
double u= (cx*dy2-cy*dx2)/temp;
double v=(cx*dy1-cy*dx1)/temp;
if(u>=0 && u<=1 && v>=0 && v<=1)
{
p1.x=first->head->x+dx1*u;
p1.y=first->head->y+dy1*u;
Point *head;
Point *end;
public:
OtherMethod();
}
//判断两个矩形是否相交或具有包含关系
bool RectangleCross(Rectangle one ,Rectangle two)
{
if(one.bottom>two.top || one.right<two.left || one.left>two.right || one.top >two.bottom)
空间数据拓扑关系的自动生成
冯文钊
拓扑空间关系是一种对空间结构进行明确定义的数学方法,具有拓扑关系的矢量数据结构就是拓扑数据结构。矢量数据拓扑关系在空间数据的查询和分析过程中非常重要,拓扑数据结构是地理信息系统分析和应用功能所必需的,它描述了基本空间目标点、线、面之间的关联、邻接和包含关系。拓扑空间关系信息是空间分析、辅助决策的等的基础,也是GIS区别于CAD(计算机辅助设计)等的主要标志。拓扑空间关系的自动建立算法是GIS中的关键和难点算法之一,国内外对该问题一直在进行研究。而且,由于拓扑关系自动生成与维护的复杂性,GIS学术界研究人员针对GIS是否需要拓扑关系,问题是以一种什么样的方式来进行拓扑空间关系表达。对于拓扑关系的自动建立问题,研究的焦点是如何提高算法与过程的效率和自动化程度,本章将讲述其实现的基本步骤和要点。
6.多边形内部标识号的自动生成。
事实上,拓扑关系的生成过程中还涉及到许多工作,例如弧段两端角度的计算、悬挂结点和悬线的标识、多边形面积计算、点在多边性内外的判别等。
第一节拓扑关系的计算机表达
一、拓扑结点
结点用来描述如管线的交点、道路路口等现实世界的特征对象,结点可以用来检测弧段与弧段的连接关系和多边形特征是否能正确地完成。只与一条弧段相连接的起点或终点叫做悬挂结点。如图1所示P点就是悬挂结点:
多边形号
弧段号
Pi
AiAjAk……
表4多边形——弧段关系表
第二节弧段处理算法
拓扑关系自动建立的第一步就是处理弧段,使得弧段不存在自相交和相交现象。本小节主要解决弧段的处理问题。
一、直线段相交的判断方法
直线相交的判定方法有很多种,这里介绍较快的一种算法。
设直线L过点 和点 ,则直线L的方程可以表示为: ,将直线方程化为参数方程有: 其中 。
}
三、拓扑面及其表示
拓扑面是由一条或若干条弧段首尾相连接而成的边线所包含的区域,内部包含有其它拓扑面的拓扑面一般称为复杂面,被包含的拓扑面称为岛,没有岛的拓扑面称为简单面,如图3所示。对于拓扑面也可以定义正反方向,一般定义为:当沿拓扑面的边界前进时,被弧段所包围的面域始终处于弧段的右侧时的方向就是正方向,反之,则是反方向,如图4所示,箭头所指向的方向就是正方向,可以看出对于拓扑面的外边界,顺时针方向是正方向,而对于内边界逆时针方向就是正方向。
return true;
}
return false;
}
class Line
{
friend LineCross(Line * first,Line * second,Point & p1,Point & p2);
public:
Line(Point *,Point *);
~Line();
private:
public:
Node() {…}; //构造函数
~Node() {…}; //析构函数
other Method…; //其他公共操作
}
二、拓扑弧段及其表示
拓扑弧段指处于两个结点之间的点序列串,可以给弧段定义一个方向,或者定义为数字化弧段时从一个结点到另一个结点的采点方向,或者硬性定义一个方向,定义方向后弧段开始的结点就称为起始结点,弧段结束的结点就称为结束结点,由起始结点到终止结点的方向称为“起终方向”,由终止结点到起始结点的方向称为“终起方向”。弧段起终方向左侧的多边形称为弧段的左多边形,弧段起终方向右侧的多边形称为弧段的右多边形,如果弧段的起始结点或终止结点只与一条弧段相关联,则该弧段称为悬挂弧段,如图2所示弧段L为悬挂弧段。一般可以通过标识悬挂弧段来检测原始矢量数据的质量。
拓扑关系生成后,拓扑结点,拓扑弧段和拓扑面之间的关系如下几张表所示:
弧段号
结点号
A0
A1
.
An
N00N10
N10N11
.
NN0NN1
表1弧段——结点关系表
结点号
弧段号
Ni
AiAjAk……
表2结点——弧段关系表
弧段号
左多边形号
右多边形号
A0
A1
.
An
PL0
PL1
.
PLn
PR0
PR1
.
PRn
表3弧段——多边形关系表
设有两条直线L1和L2,它们的参数方程分别为:
和
判断两线段有无交点的关键变为判断 和 是否符合不等式 且 。令:
,
,
,
有: ,
如果 =0,说明两线段平行或者重合,没有交点,或者交点在两线段的头或尾上,否则如果满足不等式 且 ,两线段有交点,交点在两线段的中间。
二、自相交弧段处理
具有自相交特征的弧段至少具有四个(结)节点,由三个点或两个点组成的弧段不可能自相交。依次取出每一条弧段,如果弧段的(结)节点个数不少于四个,就利用直线段相交的方法,对组成弧段的各直线段进行判断,如果相交,将线段断开为两条,自相交的弧段可能不止有一处相交,可以通过递归的方法来将弧段分开,算法如下:
L(悬挂弧段)
图2
图1
弧段一般包括:弧段号、弧段节点坐标串、弧段起始和终止结点、弧段左右多边形,弧段的数据结构可以表示如下:
class Arc
{
private:
long _ID; //弧段号
vector<Point > _Points; //弧段节点坐标串指针
Node * _start; //起始结点指针
简单面复杂面
图3
图4
多边形一般包括:多边形号、中心点坐标、多边形属性数据、多边形的组成弧段号、多边形岛的信息,考虑到组成弧段的方向和多边形顶点序列的方向存在的可能的不一致性以及效率问题,可以改为记录下组成多边形的弧段指针和方向性信息,即弧段与多边形的方向是否一致,对于岛的信息则通过将构成变形的边线分块来处理的方式体现,比如多边形包含岛屿,则可以使多边形的外边界成为多边形的第一部分,岛屿作为多边形的二、三、四等部分的方式加以解决。多边形的数据结构可以表示如下:
}
private:
long _PolygonID;
Point _CenterPoint;
vector<Part *> _Parts;
public:
Polygon() {…};
~Polygon() {…};
OtherMethod() {…};
OtherProperty() {…};
}
四、拓扑结点、弧段和面之间的关系
Node * _end; //终止结点指针
Polygon * _LeftPolygon; //弧段左多边形指针
Polygon * _RightPolygon; //弧段右多边形指针
public:
Arc() {…}; //构造函数
~Arc() {…}; //析构函数
OtherMethod…; //其他公共操作
图1
结点一般包括:结点号、结点坐标、与该结点连接的弧段集合,结点的数据结构可以表示如下:
class Node
{
private:
long _ID; //结点号
Point * _Point; //指向结点坐标的指针
vector<Arc<Point > *> ArcCollection ; //与该结点相联接的弧段集合指//针
{
return false;
}
return true;
}
//判断线段是否与矩形相交或被矩形包含
bool LineCrossRectangle(Line line ,Rectangle rect)
{
Rectangle rectofline=line.MBR();
returnRectangleCross(rectofline,rect);
}
}
if(IsSelfCross)
{
break;
}
}
if(!IsSelfCross)
{
NewArcs.push_back(arc);
}
else
{
SelfCrossDeal(first);
SelfCrossDeal(second);
}
}
void DealSelfCross()
{
typedeflist::iteratorPosition;
class Polygon
{
public:
class Part
{
private:
typedef pair<Arc<Point> * ,bool > ArcElement;
vector<ArcElement> _Arcs;
public:
Part() {…};
~Part() {…};
OtherMethod() {…};
弧段相交打断处理的算法描述如下:
//计算两直线段的交点情况
bool LineCross(Line * first, Line * second, Point & p1)
{
double dx1=first->end->x-first->head->x;
double dx2=second->end->x-second->head->x;
for(Position ite=Arcs.begin();ite!=Arcs.end();ite++)
{
Arc * arc =*ite;
BreakArc(arc);
}
}
三、弧段相交打断处理
弧段与弧段相交关系的判断,可以通过取每一条弧段,与其他未判断过的所有弧段目标进行相交关系判断而得,从而要进行 次判断,具体方法为,取出第一条弧段,与其他 条弧段进行相交判断,求得交点后,将交点分别插入第一条弧段和与其相交弧段的对应位置上,并记录位置,将第一条弧段与所有其他弧段的相交关系判断完毕后,通过记录下的交点位置将第一条弧段分割,然后依次取出下一条弧段进行同样的处理,直到所有弧段处理完毕。
double dy2=second->end-ቤተ መጻሕፍቲ ባይዱy-second->head->y;
double cx=second->head->x-first->head->x;
double cy=second->head->y-first->head->y;
由于GIS的数据量大,造成了判断的工作量大,效率低下的弊端,在判断两条弧段的关系时,应尽可能的减少计算量,减少计算量的工作可以分两步来做,首先是判断两条弧段的最小矩形壁包(Minimum bouding rectangle,MBR)是否相交或具有包含关系,如果不相交或没有包含关系,那么可以断定两条弧段是不互相交的,如果相交或具有包含关系,则进一步判断第一条弧段的每一条组成线段是否和第二条弧段的MBR相交或被包含,如果不相交或没有被包含则可以判断这一部分线段不会和第二条弧段相交,否则可以使用这一条线段与组成第二条弧段的各个线段进行相交关系的判定来确定交点。
拓扑关系自动生成算法的一般过程为:
1.弧段处理,使整幅图形中的所有弧段,除在端点处相交外,没有其他交点,即没有相交或自相交的弧段。
2.结点匹配,建立结点、弧段关系。
3.建立多边形,以左转算法或右转算法跟踪,生成多边形,建立多边形与弧段的拓扑关系。
4.建立多边形与多边形的拓扑关系。
5.调整弧段的左右多边形标识号。
List<Arc*> Arcs;//弧段集合
List<Arc*> NewArcs;//处理后的弧段集合
void BreakArc(Arc *arc)
{
Arc * first=0;//打断后的第一部分
Arc * second=0;//打断后的第一部分
bool IsSelfCross=false;
int LineCountofArc=弧段所包含的直线段数目;
for(int i=0;i<LineCountofArc-2;i++)
{
for(int j=i+2;j<LineCountofArc;j++)
{
if(直线段i和直线段j相交)
{
将交点P插如弧段,并在P处将弧段断为两截,分别存入first和second
中;
IsSelfCross=true;
Break;
double temp=dx1*dy2-dy1*dx2;
double u= (cx*dy2-cy*dx2)/temp;
double v=(cx*dy1-cy*dx1)/temp;
if(u>=0 && u<=1 && v>=0 && v<=1)
{
p1.x=first->head->x+dx1*u;
p1.y=first->head->y+dy1*u;
Point *head;
Point *end;
public:
OtherMethod();
}
//判断两个矩形是否相交或具有包含关系
bool RectangleCross(Rectangle one ,Rectangle two)
{
if(one.bottom>two.top || one.right<two.left || one.left>two.right || one.top >two.bottom)
空间数据拓扑关系的自动生成
冯文钊
拓扑空间关系是一种对空间结构进行明确定义的数学方法,具有拓扑关系的矢量数据结构就是拓扑数据结构。矢量数据拓扑关系在空间数据的查询和分析过程中非常重要,拓扑数据结构是地理信息系统分析和应用功能所必需的,它描述了基本空间目标点、线、面之间的关联、邻接和包含关系。拓扑空间关系信息是空间分析、辅助决策的等的基础,也是GIS区别于CAD(计算机辅助设计)等的主要标志。拓扑空间关系的自动建立算法是GIS中的关键和难点算法之一,国内外对该问题一直在进行研究。而且,由于拓扑关系自动生成与维护的复杂性,GIS学术界研究人员针对GIS是否需要拓扑关系,问题是以一种什么样的方式来进行拓扑空间关系表达。对于拓扑关系的自动建立问题,研究的焦点是如何提高算法与过程的效率和自动化程度,本章将讲述其实现的基本步骤和要点。
6.多边形内部标识号的自动生成。
事实上,拓扑关系的生成过程中还涉及到许多工作,例如弧段两端角度的计算、悬挂结点和悬线的标识、多边形面积计算、点在多边性内外的判别等。
第一节拓扑关系的计算机表达
一、拓扑结点
结点用来描述如管线的交点、道路路口等现实世界的特征对象,结点可以用来检测弧段与弧段的连接关系和多边形特征是否能正确地完成。只与一条弧段相连接的起点或终点叫做悬挂结点。如图1所示P点就是悬挂结点:
多边形号
弧段号
Pi
AiAjAk……
表4多边形——弧段关系表
第二节弧段处理算法
拓扑关系自动建立的第一步就是处理弧段,使得弧段不存在自相交和相交现象。本小节主要解决弧段的处理问题。
一、直线段相交的判断方法
直线相交的判定方法有很多种,这里介绍较快的一种算法。
设直线L过点 和点 ,则直线L的方程可以表示为: ,将直线方程化为参数方程有: 其中 。
}
三、拓扑面及其表示
拓扑面是由一条或若干条弧段首尾相连接而成的边线所包含的区域,内部包含有其它拓扑面的拓扑面一般称为复杂面,被包含的拓扑面称为岛,没有岛的拓扑面称为简单面,如图3所示。对于拓扑面也可以定义正反方向,一般定义为:当沿拓扑面的边界前进时,被弧段所包围的面域始终处于弧段的右侧时的方向就是正方向,反之,则是反方向,如图4所示,箭头所指向的方向就是正方向,可以看出对于拓扑面的外边界,顺时针方向是正方向,而对于内边界逆时针方向就是正方向。
return true;
}
return false;
}
class Line
{
friend LineCross(Line * first,Line * second,Point & p1,Point & p2);
public:
Line(Point *,Point *);
~Line();
private:
public:
Node() {…}; //构造函数
~Node() {…}; //析构函数
other Method…; //其他公共操作
}
二、拓扑弧段及其表示
拓扑弧段指处于两个结点之间的点序列串,可以给弧段定义一个方向,或者定义为数字化弧段时从一个结点到另一个结点的采点方向,或者硬性定义一个方向,定义方向后弧段开始的结点就称为起始结点,弧段结束的结点就称为结束结点,由起始结点到终止结点的方向称为“起终方向”,由终止结点到起始结点的方向称为“终起方向”。弧段起终方向左侧的多边形称为弧段的左多边形,弧段起终方向右侧的多边形称为弧段的右多边形,如果弧段的起始结点或终止结点只与一条弧段相关联,则该弧段称为悬挂弧段,如图2所示弧段L为悬挂弧段。一般可以通过标识悬挂弧段来检测原始矢量数据的质量。
拓扑关系生成后,拓扑结点,拓扑弧段和拓扑面之间的关系如下几张表所示:
弧段号
结点号
A0
A1
.
An
N00N10
N10N11
.
NN0NN1
表1弧段——结点关系表
结点号
弧段号
Ni
AiAjAk……
表2结点——弧段关系表
弧段号
左多边形号
右多边形号
A0
A1
.
An
PL0
PL1
.
PLn
PR0
PR1
.
PRn
表3弧段——多边形关系表
设有两条直线L1和L2,它们的参数方程分别为:
和
判断两线段有无交点的关键变为判断 和 是否符合不等式 且 。令:
,
,
,
有: ,
如果 =0,说明两线段平行或者重合,没有交点,或者交点在两线段的头或尾上,否则如果满足不等式 且 ,两线段有交点,交点在两线段的中间。
二、自相交弧段处理
具有自相交特征的弧段至少具有四个(结)节点,由三个点或两个点组成的弧段不可能自相交。依次取出每一条弧段,如果弧段的(结)节点个数不少于四个,就利用直线段相交的方法,对组成弧段的各直线段进行判断,如果相交,将线段断开为两条,自相交的弧段可能不止有一处相交,可以通过递归的方法来将弧段分开,算法如下:
L(悬挂弧段)
图2
图1
弧段一般包括:弧段号、弧段节点坐标串、弧段起始和终止结点、弧段左右多边形,弧段的数据结构可以表示如下:
class Arc
{
private:
long _ID; //弧段号
vector<Point > _Points; //弧段节点坐标串指针
Node * _start; //起始结点指针
简单面复杂面
图3
图4
多边形一般包括:多边形号、中心点坐标、多边形属性数据、多边形的组成弧段号、多边形岛的信息,考虑到组成弧段的方向和多边形顶点序列的方向存在的可能的不一致性以及效率问题,可以改为记录下组成多边形的弧段指针和方向性信息,即弧段与多边形的方向是否一致,对于岛的信息则通过将构成变形的边线分块来处理的方式体现,比如多边形包含岛屿,则可以使多边形的外边界成为多边形的第一部分,岛屿作为多边形的二、三、四等部分的方式加以解决。多边形的数据结构可以表示如下:
}
private:
long _PolygonID;
Point _CenterPoint;
vector<Part *> _Parts;
public:
Polygon() {…};
~Polygon() {…};
OtherMethod() {…};
OtherProperty() {…};
}
四、拓扑结点、弧段和面之间的关系
Node * _end; //终止结点指针
Polygon * _LeftPolygon; //弧段左多边形指针
Polygon * _RightPolygon; //弧段右多边形指针
public:
Arc() {…}; //构造函数
~Arc() {…}; //析构函数
OtherMethod…; //其他公共操作
图1
结点一般包括:结点号、结点坐标、与该结点连接的弧段集合,结点的数据结构可以表示如下:
class Node
{
private:
long _ID; //结点号
Point * _Point; //指向结点坐标的指针
vector<Arc<Point > *> ArcCollection ; //与该结点相联接的弧段集合指//针
{
return false;
}
return true;
}
//判断线段是否与矩形相交或被矩形包含
bool LineCrossRectangle(Line line ,Rectangle rect)
{
Rectangle rectofline=line.MBR();
returnRectangleCross(rectofline,rect);
}
}
if(IsSelfCross)
{
break;
}
}
if(!IsSelfCross)
{
NewArcs.push_back(arc);
}
else
{
SelfCrossDeal(first);
SelfCrossDeal(second);
}
}
void DealSelfCross()
{
typedeflist::iteratorPosition;
class Polygon
{
public:
class Part
{
private:
typedef pair<Arc<Point> * ,bool > ArcElement;
vector<ArcElement> _Arcs;
public:
Part() {…};
~Part() {…};
OtherMethod() {…};
弧段相交打断处理的算法描述如下:
//计算两直线段的交点情况
bool LineCross(Line * first, Line * second, Point & p1)
{
double dx1=first->end->x-first->head->x;
double dx2=second->end->x-second->head->x;
for(Position ite=Arcs.begin();ite!=Arcs.end();ite++)
{
Arc * arc =*ite;
BreakArc(arc);
}
}
三、弧段相交打断处理
弧段与弧段相交关系的判断,可以通过取每一条弧段,与其他未判断过的所有弧段目标进行相交关系判断而得,从而要进行 次判断,具体方法为,取出第一条弧段,与其他 条弧段进行相交判断,求得交点后,将交点分别插入第一条弧段和与其相交弧段的对应位置上,并记录位置,将第一条弧段与所有其他弧段的相交关系判断完毕后,通过记录下的交点位置将第一条弧段分割,然后依次取出下一条弧段进行同样的处理,直到所有弧段处理完毕。