地理信息系统算法基础上机题目.docx
《地理信息系统算法基础上机题目.docx》由会员分享,可在线阅读,更多相关《地理信息系统算法基础上机题目.docx(6页珍藏版)》请在冰点文库上搜索。
地理信息系统算法基础上机题目
YLChen2013.4
1、已知一线段AB,在某个方向选择一点P,输入距离d,求线段AB延长距离d后的点坐
标
privatePointFGetPoint(Pointpt1,Pointpt2,floatdis)
{
floatX,Y;//用于记录新点的X、Y坐标值
doubleL=Math.Sqrt((pt1.X-pt2.X)*(pt1.X-pt2.X)+(pt1.Y-pt2.Y)
*(pt1.Y-pt2.Y));//求出pt1和pt2两点的距离
//根据pt1和pt2两点中,哪个点离光标当前点最近,求出新点的X、Y坐标值
if(Math.Abs(tmpPoint.X-pt2.X){
X=(float)(pt2.X+(pt2.X-pt1.X)*dis/L);
Y=(float)(pt2.Y+(pt2.Y-pt1.Y)*dis/L);
returnnewPointF(X,Y);
}
else
{
X=(float)(pt1.X+(pt1.X-pt2.X)*dis/L);
Y=(float)(pt1.Y+(pt1.Y-pt2.Y)*dis/L);
returnnewPointF(X,Y);
}
}
2、判断两线段是否相交
publicstaticboolIsIntersected(SimpleLineL1,SimpleLineL2)
{
//获取两条线段的端点
PointP1=L1.Nodes[0];
PointP2=L1.Nodes[1];
PointQ1=L2.Nodes[0];
PointQ2=L2.Nodes[1];
//求向量P1Q1,P2Q1,Q2Q1
PointP1Q1=newPoint(P1.X-Q1.X,P1.Y-Q1.Y);
PointP2Q1=newPoint(P2.X-Q1.X,P2.Y-Q1.Y);
PointQ2Q1=newPoint(Q2.X-Q1.X,Q2.Y-Q1.Y);
//判断线段P1P2是否跨立线段Q1Q2,当点P1和P2在线段两侧时,则线段P1P2
跨立线段Q1Q2。
if(((P1Q1.X*Q2Q1.Y-Q2Q1.X*P1Q1.Y)>=0)&&((P2Q1.X*Q2Q1.Y-Q2Q1.X
*P2Q1.Y)<=0))
returntrue;
elseif(((P1Q1.X*Q2Q1.Y-Q2Q1.X*P1Q1.Y)<=0)&&((P2Q1.X*Q2Q1.Y
-Q2Q1.X*P2Q1.Y)>=0))
returntrue;
else
returnfalse;
}
3、多边形重心计算
staticpublicPointFCenterOfPolygon(SimplePolygonpolygon)
{
PointP1=polygon.Nodes[0];//取出第一点作为所有三角形的公共顶点
PointP2;//P2和P3用于存储三角形的其他两个顶点
PointP3;
ListtempPointList=newList();//存储所有三角形的重(中)
心
doubleareaOfPolygon=0;//多边形的面积
doubleX=0;//X、Y:
多边形的重(中)心
doubleY=0;
//计算所有三角形的重(中)心,存储在tempPointList中
for(inti=1;i{
P2=polygon.Nodes[i];
P3=polygon.Nodes[i+1];
tempPointList.Add(newPointF((P1.X+P2.X+P3.X)/3f,(P1.Y+P2.Y+
P3.Y)/3f));
}
//计算多边形的面积:
所有三角形的面积之和
for(inti=1;i{
P2=polygon.Nodes[i];
P3=polygon.Nodes[i+1];
areaOfPolygon+=Math.Abs(Vector.VecCross(P1,P2,P3));
}
//将三角形的重(中)心加权平均求得多边形的重(中)心
//各个三角形重(中)心的权重即是三角形的面积所占多边形面积的比例
for(inti=1;i{
P2=polygon.Nodes[i];
P3=polygon.Nodes[i+1];
X+=tempPointList[i-1].X*Math.Abs(Vector.VecCross(P1,P2,P3))/
areaOfPolygon;
Y+=tempPointList[i-1].Y*Math.Abs(Vector.VecCross(P1,P2,P3))/
areaOfPolygon;
}
PointFtempPoint=newPointF((float)X,(float)Y);
returntempPoint;
}
4、编程实现八方向矢量线栅格化
提示:
栅格单元的宽度和长度为10个像素,点的坐标信息都是工作区坐标信息
privatevoidEightdirRasterized(Pointp1,Pointp2)
{
//线段的斜率
floatb=((float)((p2.Y-p1.Y)))/(p2.X-p1.X);
floatb1=((float)((p2.X-p1.X)))/(p2.Y-p1.Y);
//求出这两个端点位置的列数差和行数差
intdeltaX=Math.Abs(p2.X-p1.X),deltaY=Math.Abs(p2.Y-p1.Y);
//若列数差大于行数差,则逐列求出本列中心线与过这两个端点的直线的交点
if(deltaX>deltaY)
{
for(floatcol=p1.X+1.5f,row;col{
row=(col-p1.X)*b+p1.Y;
collectofpoint.Add(newPoint((Int32)Math.Truncate(col),
(Int32)Math.Truncate(row)));
}
}
else//若列数差小于行数差,则逐行求出本行中心线与过这两个端点的直线的交
点
{
for(floatrow=p1.Y+1.5f,col;row{
col=(row-p1.Y)*b1+p1.X;
collectofpoint.Add(newPoint((Int32)Math.Truncate(col),
(Int32)Math.Truncate(row)));
}
}
}
5、编程实现全路径矢量线栅格化
提示:
栅格单元的宽度和长度为10个像素,点的坐标信息都是工作区坐标信息
privatevoidFullPathRasterized(PointFp1,PointFp2)
{
floata=(p2.Y-p1.Y)/(p2.X-p1.X);//计算矢量倾角的正切
floatdeltaX=Math.Abs(p2.X-p1.X),deltaY=Math.Abs(p2.Y-p1.Y);//计
算行数差和列数差
floatstartCol,endCol=0;
if(deltaX>=deltaY)
{
for(inti=((int)p1.Y)/10;i<=((int)p2.Y)/10;i++)
{
if(i==((int)p1.Y)/10)
startCol=((i*10-p1.Y)/a+p1.X)/10;
else
startCol=endCol;
endCol=(((i+1)*10-p1.Y)/a+p1.X)/10;
if(i==((int)p1.Y)/10&&startCol<((int)p1.X)/10)
startCol=((int)p1.X)/10;
if(i==((int)p2.Y)/10&&endCol>((int)p2.X)/10)
endCol=((int)p2.X)/10;
while(startCol<=endCol)
{
resultOfFullPathRasterized.Add(new
PointF((int)Math.Truncate(startCol),i));
startCol++;
}
}
}
}
6、编程实现间隔取点法达到矢量数据的压缩
staticpublicSimpleLineCompressByInterval(SimpleLineline,intInterval)
{
SimpleLinenewSimpleLine=newSimpleLine();
inti=0;
if(Interval>=line.Nodes.Count()-2)
{
MessageBox.Show("间隔点数值Interval太大,将返回原始线要素");
returnline;
}
else
{
while(i{
newSimpleLine.Add(line.Nodes[i]);
i+=(Interval+1);
}
}
newSimpleLine.Add(line.Nodes.Last());//保留末点
returnnewSimpleLine;
}
7、求点P(x,y)到线段l的最短距离
publicstaticfloatGetDistancePointToSegment(PointP,PointP0,PointP1)
{
PointP0P1=newPoint(P1.X-P0.X,P1.Y-P0.Y);//求向量P0P1
PointP0P=newPoint(P.X-P0.X,P.Y-P0.Y);//求向量P0P
intc1,c2;//用于存储向量的数量积结果值
c1=P0P1.X*P0P.X+P0P1.Y*P0P.Y;//计算向量P0P1和向量P0P的数量积
c2=P0P1.X*P0P1.X+P0P1.Y*P0P1.Y;//计算向量P0P和P0P的数量积
//若向量P0P1和向量P0P的数量积小于等于0时,意味着P点位于线段P0P1的左
边,此时返回距离P0P;
if(c1<=0)
return(float)Math.Sqrt(P0P.X*P0P.X+P0P.Y*P0P.Y);
//若向量P0P1和向量P0P的数量积小于等于向量P0P和P0P的数量积,意味着P
点位于线段P0P1的右边,此时返回距离P1P
if(c2<=c1)
return(float)Math.Sqrt((P.X-P1.X)*(P.X-P1.X)+(P.Y-P1.Y)*(P.Y
-P1.Y));
//若不符合上面的条件,则点P的垂足位于线段P0P1上,下面计算垂足和点P到
垂足的距离,防返回
//使用直线的参数方程求垂足
floatb=((float)c1)/c2;
PointFPb=newPointF(P0.X+b*P0P1.X,P0.Y+b*P0P1.Y);
return(float)Math.Sqrt((P.X-Pb.X)*(P.X-Pb.X)+(P.Y-Pb.Y)*(P.Y
-Pb.Y));
}
8、编写链式编码程序实现栅格数据的压缩
9、编程:
用垂距法实现矢量数据的压缩
staticpublicSimpleLineCompressByCloserange(SimpleLineline,doubletolerance)
{
boolIsDeleted=false;//标记是否删除了超过容差限制的节点,若删除了,这
标记为true,否则标记为false
intnum=line.Nodes.Count();//折线line包含的节点数量
SimpleLinenewLine=newSimpleLine();//存储折线line压缩后的结果
newLine.Add(line.Nodes[0]);
PointP1=Point.Empty;
PointP2=Point.Empty;
PointP3=Point.Empty;
for(inti=0;i{
//循环一次之后,若没有删除节点,则将三个节点依次后移一个节点
//若删除了节点,则将当前节点的前一个节点以后后两个节点依次赋给P1、P2
和P3
if(!
IsDeleted)
{
P1=line.Nodes[i];
P2=line.Nodes[i+1];
P3=line.Nodes[i+2];
}
else
{
P1=line.Nodes[i-1];
P2=line.Nodes[i+1];
P3=line.Nodes[i+2];
}
//若垂距大于容差tolerance,则保留该点,即将其添加到折线newLine中
if(Math.Abs(Vector.VecCross(P1,P2,P3)/Vector.GetLength(P1,P3))>
tolerance)
{
newLine.Add(P2);
IsDeleted=false;
}
else
{
IsDeleted=true;
}
}
newLine.Add(line.Nodes[num-1]);
returnnewLine;
}